我有一个查询从两个表中检索数据。
table1
有一个int字段,table1_id
是主键。
table2
有两个字段; table1_id
,一个int字段(引用table1.table1_id
)和field1
,一个位字段。
table2
上有三个索引:table1_id
,field1
和table1_id_field1
(索引位于名称所指示的字段上)。
我有以下查询:
SELECT * FROM table1 t1
LEFT JOIN table2 t2
ON t2.table1_id = t1.table1_id
WHERE t2.table1_id IN
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
此查询的计划(使用EXPLAIN
获得)是:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range table1_id,field1,table1_id_field1 table1_id_field1 8 NULL 29858 Using where
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 8 db1.t2.table1_id 1
现在,我在查询中添加了一个额外的where子句,如下所示:
SELECT * FROM table1 t1
LEFT JOIN table2 t2
ON t2.table1_id = t1.table1_id
WHERE t2.table1_id IN
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
**AND field1 = 0**
查询不再像以前那样使用高效的索引;这是查询计划:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref table1_id,field1,table1_id_field1 field1 2 const 98913 Using where
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 8 db1.t2.table1_id 1
它现在搜索的行数(98913)比以前更多(29858),并且它不再使用之前在原始查询中使用的索引(它使用的是field1
而不是table1_id_field1
。
我的问题是:
有没有理由说第二个带附加子句的查询没有使用它在第一个查询中使用的索引?
除了使用FORCE INDEX
之外,有什么方法可以让mysql选择更高效的索引?也许我需要添加另一个索引?
答案 0 :(得分:0)
我猜想有太多的冗余索引会使优化器混淆,所以选择了错误的索引。
在我看来,在table2上只有一个索引table1_id_field1
就足够了,因为table1_id
是一个前导列,所以这个索引可用于强制执行FK;因此,不需要table1_id
上的索引。 field1
上的索引不能选择(因为它在位字段上)是有效的。