用一个两列排序方向不一样的ORDER BY,对比有没有方向匹配的降序复合索引,看MySQL 8.0的降序索引真实省下了什么。
customer_id升序、created_at降序,这种混合方向在业务里很常见(比如按客户分组、组内按时间倒序)。
代码SELECT customer_id, created_at FROM orders WHERE customer_id BETWEEN 1 AND 5000 ORDER BY customer_id ASC, created_at DESC;
-> Sort: orders.customer_id, orders.created_at DESC
-> Index range scan on orders using idx_cust ...虽然idx_cust已经按customer_id排好了序,但索引内部created_at这一列存的是升序,和查询要的降序方向不一致,MySQL没法直接利用索引顺序,只能先按索引取出数据,再单独做一次Sort。
代码CREATE INDEX idx_cust_created_desc ON orders(customer_id ASC, created_at DESC);
-> Filter: (orders.customer_id in (100,200,300))
-> Covering index range scan on orders using idx_cust_created_desc ... ← 没有Sort了索引定义里显式声明了customer_id ASC, created_at DESC,这个方向组合和查询要的ORDER BY完全一致,MySQL真实可以直接按索引的物理存储顺序读出数据,Sort这一步真实从执行计划里消失了,直接变成Covering index range scan(顺带还是个覆盖索引,不用回表)。
没有降序索引,走Sort: 64177 微秒 (约64.2毫秒) 有匹配方向的降序索引: 26036 微秒 (约26.0毫秒) ← 快约2.5倍
每一步都是本文上面用EXPLAIN FORMAT=TREE和真实计时跑出来的原始结果。
CREATE INDEX ... (col1 ASC, col2 DESC):MySQL 8.0起真实支持的降序索引