我有一个包含 3 个字段的表“t_table1”:
`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
这种情况下它使用了我的索引。 所以请为我解释一下:
为什么SQL1不能使用索引?
对于 SQL1,我如何编辑索引或重写 SQL 以更快地执行?
谢谢!
最佳答案
查询优化器使用许多数据点来决定如何执行查询。其中之一是索引的选择性。使用索引可能需要比表扫描返回的每行更多的磁盘访问,因为引擎必须读取索引然后获取实际行(除非仅从索引可以满足整个查询)。随着索引的选择性降低(即更多行符合条件),使用该索引的效率会下降。在某些时候,进行全表扫描会变得更便宜。
在您的第二个示例中,优化器能够确定您提供的值只会导致获取一行,因此索引查找是正确的方法。
在第一个示例中,值的选择性不是很强,估计从 1776 行中返回了 1042 行。使用索引将导致搜索索引,构建所选行引用的列表,然后获取每一行。由于选择了如此多的行,使用索引会导致比仅线性扫描整个表并过滤行更多的工作。
关于mysql索引不能用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14472027/