为什么SQL查询中ORDER BY字段排序失效,是因它不在驱动表列中吗?
- 内容介绍
- 相关推荐
本文共计1001个文字,预计阅读时间需要5分钟。
在MySQL中使用JOIN查询并应用ORDER BY时,仅允许对驱动表(即被选作外层循环的表)的字段直接利用索引排序。如果ORDER BY指向的是被驱动表(即内层表)的字段,即使该字段上有索引,优化器也很大概率会放弃使用索引排序,转而使用文件排序(Using filesort)。这就是你看到排序失效的真正原因。
比如执行:SELECT u.name, o.order_id FROM users u JOIN orders o ON u.id = o.user_id ORDER BY o.create_time DESC,即使 orders.create_time 有索引,只要 orders 是被驱动表(EXPLAIN 中 type 为 ref 或 range,且 rows 显著大于驱动表),MySQL 就无法按该索引顺序取数据,只能先拼完结果集再内存/磁盘排序。
怎么快速判断哪个是驱动表
看 EXPLAIN 输出中最关键的两列:table 和 rows。MySQL 通常选择 rows 更小、过滤性更强的表作为驱动表(尤其在没有强制 STRAIGHT_JOIN 的情况下)。但注意:这个选择受统计信息影响,不是绝对的。
本文共计1001个文字,预计阅读时间需要5分钟。
在MySQL中使用JOIN查询并应用ORDER BY时,仅允许对驱动表(即被选作外层循环的表)的字段直接利用索引排序。如果ORDER BY指向的是被驱动表(即内层表)的字段,即使该字段上有索引,优化器也很大概率会放弃使用索引排序,转而使用文件排序(Using filesort)。这就是你看到排序失效的真正原因。
比如执行:SELECT u.name, o.order_id FROM users u JOIN orders o ON u.id = o.user_id ORDER BY o.create_time DESC,即使 orders.create_time 有索引,只要 orders 是被驱动表(EXPLAIN 中 type 为 ref 或 range,且 rows 显著大于驱动表),MySQL 就无法按该索引顺序取数据,只能先拼完结果集再内存/磁盘排序。
怎么快速判断哪个是驱动表
看 EXPLAIN 输出中最关键的两列:table 和 rows。MySQL 通常选择 rows 更小、过滤性更强的表作为驱动表(尤其在没有强制 STRAIGHT_JOIN 的情况下)。但注意:这个选择受统计信息影响,不是绝对的。

