mysql命令由-id vs命令由id desc命令

时间:2014-12-30 11:50:44

标签: mysql database-performance

我希望从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;

enter image description here

以下是我使用'order by -id'

的查询结果
EXPLAIN select * from test order by -id limit 10;

enter image description here

我认为这是相同的,但似乎执行计划存在差异。

3 个答案:

答案 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