我使用mysql 5.5,innoDB并且一直试图理解它的索引规则。
我遇到了与order by
相关的问题,但通过Google搜索找不到任何明确的答案。
有一个简单的表格,如test_table
:
idx : index (int), Primary key, auto-increment
test_datetime : datetime, index(test_datatime)
some_dummy_col1 : dummy1(varchar)
some_dummy_col2 : dummy2(int)
我将test_datetime
编入索引并尝试了一个类似的查询:
select idx, test_datetime from test_table order by test_datetime desc;
正在运行explain
显示了我想要的内容(type: index, Extra: using index
等等......)但是当我尝试按select *
获取整行时,explain
显示{{ 1}}。
我试图将测试数据的数量增加到300,000行左右。它仍然会产生相同的结果。
有人可以解释为什么选择索引列只有效但选择using filesort
不起作用吗?
提前致谢。
答案 0 :(得分:0)
首先考虑查询:
select t.test_datetime
from test_table t
order by test_datetime desc;
您拥有的索引此查询。这意味着索引中的所有列都在查询中。因此,SQL引擎可以轻松返回结果:只需按顺序读取索引并从索引返回test_datetime
列。
将select
列表展开为:
select t.*
from test_table t
order by test_datetime desc;
然后SQL引擎不再只是读取索引。相反,它有两个选择。一种是按顺序读取索引(满足order by
)。然后,对于索引中的每个记录,它需要查找数据页中的记录以获取其他列。
另一种方法是对所有数据进行排序。 MySQL决定对所有数据进行排序"选项是您环境中此特定查询的最佳选择。
这并不像听起来那么疯狂。如果你的表不适合内存,那么索引方法可能会导致一些名为" thrashing"。这是读取数据的最坏情况,甚至可能比进行排序更慢。
答案 1 :(得分:0)
EXPLAIN计划中的“使用索引”说明意味着仅使用 索引,即仅从索引中获取所需的列,而不必从表中读取任何行。这称为仅索引查询。
但仅当select-list仅包含索引定义中包含的列时,它才有效。 InnoDB还允许主键列,因为即使您没有以这种方式定义索引,所有二级索引也隐式包含PK列。
如果您使用SELECT *
,那么您将无法获得“使用索引”(除非您的表只有几个字段且索引全部覆盖它们)。但这并不意味着MySQL根本没有使用索引。它只是意味着除了读取索引外还必须读取行。