2013-01-23 49 views
1

我有一个表“t_table1'包含3个字段:MySQL索引的不能使用

`field1` tinyint(1) unsigned default NULL, 
`field2` tinyint(1) unsigned default NULL, 
`field3` tinyint(1) unsigned NOT NULL default ’0′, 

和指数:

KEY `t_table1_index1` (`field1`,`field2`,`field3`), 

当我运行此SQL1:

EXPLAIN SELECT * FROM table1 AS c WHERE c.field1 = 1 AND c.field2 = 0 AND c.field3 = 0 

然后显示:

Select type: Simple 
tyle: All 
possible key: t_table1_index1 
key: NULL 
key_len: NULL 
rows: 1042 
extra: Using where 

我认为这是说我的索引在这种情况下是无用的。

但是当我运行这个SQL2:

EXPLAIN SELECT * FROM table1 AS c WHERE c.field1 = 1 AND c.field2 = 1 AND c.field3 = 1 

它表明:

Select type: Simple 
tyle: ref 
possible key: t_table1_index1 
key: t_table1_index1 
key_len: 5 
ref: const, const, const 
rows: 1 
extra: Using where 

它使用我的索引这种情况。 所以请您解释一下:

  1. 为什么SQL1不能使用索引?

  2. 与SQL1,如何编辑索引或重写SQL以更快地执行?

谢谢!

+0

表中有多少行?如果索引不会缩小返回的行数,则优化器可以根本不选择使用索引。 –

+0

我的表有1776条记录。 SQL1返回10条记录,SQL2返回0条记录。 你能解释得更清楚吗?为什么SQL1不使用索引和SQL2使用索引? –

+0

可能是因为对于这些值,索引不够有选择性(它将返回超过1000行)。优化器查看它并决定读取索引,然后使用结果来获取行将比仅执行全表扫描更昂贵。在第二个示例中,查询将只选择1行。在这种情况下,使用索引然后获取单行是值得的。 –

回答

0

查询优化器使用许多数据点来决定如何执行查询。其中之一是选择性的指数。要使用索引,需要比表扫描返回更多的磁盘访问次数,因为引擎必须读取索引,然后获取实际行(除非整个查询只能通过索引来满足)。随着索引选择性下降(即更多行符合标准),使用该索引的效率下降。在某个时候,全桌面扫描会变得更便宜。

在第二个示例中,优化器能够确定您提供的值会导致只有一行被提取,因此索引查找是正确的方法。

在第一个示例中,这些值不是非常有选择性,估计有从1076年返回的1042行。使用索引将导致搜索索引,构建所选行参考列表,然后获取每行。选择这么多的行,使用索引会导致更多的工作,而不仅仅是线条扫描整个表并过滤行。