CREATE TABLE IF NOT EXISTS test (col1 INT, col2 INT);
ALTER TABLE test ADD INDEX idx_col1(col1);
ALTER TABLE test ADD INDEX idx_col2(col2);
EXPLAIN SELECT * FROM test WHERE col1>=0 AND col2<=2;
结果:
id select_type table type possible_keys key key_len ref
1 SIMPLE test range idx_col2,idx_col1 idx_col2 5 1
为什么只使用idx_col2,而不是同时使用两者。
答案 0 :(得分:1)
这是涉及范围的选择的经典问题。
索引查找的结果是表中的一行或多行。当SQL决定如何处理您的选择时,它必须首先决定使用哪个索引。在你的情况下,它是idx_col2。结果,它将知道满足的所有行(col2 <= 2)。
从这些行中,它必须删除不满足的行(col1&gt; = 0)。但是索引idx_col1在这里没有多大帮助,因为它引用了整个表而不仅仅是仍然存在问题的行。 idx_col1上的索引范围扫描将返回满足谓词的所有行,并且SQL必须找到col1 和找到两者的行col2索引范围扫描。
在几乎所有情况下,这都不会付出代价。如果从col2扫描返回的行数很小,那么SQL也可以遍历所有这些行并检查(col1&gt; = 0)而不使用索引。如果行数很大,找到匹配的行将是昂贵的。它必须考虑从col2扫描返回的所有行,并检查col1扫描中是否有匹配的行。这比仅仅检查它们是否满足(col1&gt; = 0)更昂贵。
一般来说,常规b树索引和范围(涉及不同列)不能很好地协同工作。一些RDBMS有一种特殊的空间&#34; index允许有效查询,涉及范围。
答案 1 :(得分:0)
我认为,如果你同时使用它,它需要排序两次,
它按col2排序,因此保留行逐行检查col1,
也许这是因为你的行太小了,如果有很多行,它可能会排序两次,因此使用2个索引
我不确定,只是想知道。
答案 2 :(得分:0)
如果我记得MySQL只能使用一个索引到1个表。 这是一个功能......
如果你想为两个列使用索引,你应该使用它:
ALTER TABLE test ADD INDEX idx_cols(col1, col2);
此索引应该对您的查询正确,但如果您将查询中的顺序更改为col2<=2 AND col1>=0
,则无法使用索引...