我希望从1M行的表中获取最后10行。
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`updated_date` datetime NOT NULL,
PRIMARY KEY (`id`)
)
这样做的一种方法是 -
select * from test order by -id limit 10;
**10 rows in set (0.14 sec)**
另一种方法是 -
select * from test order by id desc limit 10;
**10 rows in set (0.00 sec)**
所以我对这些查询进行了“解释” -
以下是我使用'order by desc'
的查询结果EXPLAIN select * from test order by id desc limit 10;
以下是我使用'order by -id'
的查询结果EXPLAIN select * from test order by -id limit 10;
我认为这是相同的,但似乎执行计划存在差异。
答案 0 :(得分:18)
RDBMS使用启发式方法来计算执行计划,它们不能总是确定两个语句的语义等价,因为它是一个太难的问题(在理论和实际复杂性方面)。
所以MySQL无法使用索引,因为你没有“-id”的索引,这是一个应用于字段“id”的自定义函数。看似微不足道,但RDBMS必须最大限度地减少计算计划所需的时间,因此他们会遇到简单的问题。
当找不到查询的优化(即使用索引)时,系统会回退到在任何情况下都有效的实现:扫描整个表。
答案 1 :(得分:4)
正如您在解释结果中所看到的那样,
1 :order by id
MySQL正在id
上使用索引。所以它需要只迭代 10 行,因为它已被索引。而且在这种情况下,MySQL不需要使用filesort
算法,因为它已被索引。
2 :order by -id
使用id
上的索引,MySQL 不。因此,它需要迭代所有行(例如 455952 )以获得预期结果。在这种情况下,MySQL需要使用filesort
算法,因为id
未编入索引。所以显然需要更多的时间:))
答案 2 :(得分:3)
将ORDER BY与包含键列名以外的术语的表达式一起使用:
SELECT * FROM t1 ORDER BY ABS(key);
SELECT * FROM t1 ORDER BY -key;
只索引ORDER BY子句中指定的列的前缀。在这种情况下,索引不能用于完全解析排序顺序。例如,如果您有一个CHAR(20)列,但仅索引前10个字节,则索引无法区分超过第10个字节的值,并且将需要filesort。
使用的表索引类型不按顺序存储行。例如,对于MEMORY表中的HASH索引,这是正确的。
请点击此链接:http://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html