为什么不在以下sql中使用两个索引

时间:2014-04-18 08:40:22

标签: mysql sql

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,而不是同时使用两者。

3 个答案:

答案 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,则无法使用索引...