【发布时间】:2015-07-20 07:42:44
【问题描述】:
我需要帮助以使用一个LEFT JOIN 在 SQL 查询中选择正确的索引。
我有两个表格(对象和月度报告):
CREATE TABLE some_objects (
id int(11) NOT NULL AUTO_INCREMENT,
...,
PRIMARY KEY (id),
);
CREATE TABLE month_reports (
id int(11) NOT NULL AUTO_INCREMENT,
some_object_id int(11) DEFAULT NULL,
month int(11) NOT NULL,
year int(11) NOT NULL,
...,
PRIMARY KEY (id),
INDEX IDX_123 (month, year),
INDEX IDX_456 (some_object_id),
INDEX IDX_789 (some_object_id, month, year),
CONSTRAINT FK_123 FOREIGN KEY (some_object_id)
REFERENCES some_objects (id) ON DELETE RESTRICT ON UPDATE RESTRICT
)
我需要选择在特定月份或没有报告的所有对象。我试过这个查询:
SELECT * FROM some_objects so
LEFT JOIN month_reports mr ON mr.some_object_id = so.id
WHERE
mr.month = :month
AND mr.year = :year
OR mr.id IS NULL
EXPLAIN 结果:
id select_type table type possible_keys
1 SIMPLE so ALL
1 SIMPLE mr ALL IDX_456,IDX_789
EXPLAIN 没有OR mr.id IS NULL 的结果:
id select_type table type possible_keys key ref
1 SIMPLE mr ref IDX_123,IDX_456,IDX_789 IDX_123 const,const
1 SIMPLE so eq_ref PRIMARY
但如果没有OR mr.id IS NULL,我不会得到没有报告的对象!
我应该添加哪些其他索引?我需要更改查询吗?
附:对不起我的英语。
UPD。 ANALYZE TABLE 返回“状态正常”。 EXPLAIN 结果与FORCE INDEX(10 个对象,只有一个有报告):
id select_type table type possible_keys key rows
1 SIMPLE so ALL 10
1 SIMPLE mr ref IDX_789 IDX_789 1
【问题讨论】:
-
您可以将
some_object_id添加到现有的IDX_123。 -
@Vatev 抱歉,我修复了 IDX_789。它有 some_object_id、month、year 列,并且 MySQL-server 不使用它:(
-
当行数太少时,有时会出现这种情况(如果行数很少,请添加一些)。尝试运行ANALYZE TABLE。如果这不起作用,请将
FORCE KEY(IDX_789)添加到 JOIN 并发布查询计划。同时发布行数估计值。 -
@Vatev 我将更新添加到问题中。结果正常吗?
-
看起来很正常。第一个查询计划 (
SIMPLE mr ALL) 的行估计值是多少?
标签: mysql sql optimization indexing