这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战
使用MySQL查询有两种方式能够生成有序的结果
- MySQL的排序操作
- 按照索引顺序进行扫描 后者由于只需要按照索引进行顺序扫描,速度会比前者快很多。
但是如果索引列无法满足查询结果的列,那么每次扫描一条索引记录就需要回表查询一次对应的行,由于是随机IO,因此按照“索引顺序回表查询”比“顺序全表扫描”要慢,因此尽可能在设计索引时既满足排序又可以用于查找行。
使用索引扫描进行排序的条件
如果想要索引既能满足排序,又能由于查找,需要注意以下原则
- 索引列的顺序和
ORDER BY
子句的顺序完全一致,并且排序方向相同。如下面4条查询,只有查询1和查询3的排序是完全按照索引。# 1: Using Index explain select source_system, batch_no from account_batch order by source_system, batch_no; # 2: Using Index; Using filesort explain select source_system, batch_no from account_batch order by source_system desc, batch_no desc; # 3: Using Index explain select source_system, batch_no from account_batch order by source_system desc, batch_no; # 4: Using Index; Using filesort explain select source_system, batch_no from account_batch order by batch_no, source_system
- 多表关联查询时,只有
ORDER BY
子句引用的字段全部为第一个表时才能使用索引做排序。如下面2条查询,查询2由于ORDER BY
子句包含了第二个表的字段,因此无法按照索引排序。# 1: Using index explain select a.source_system, a.template_id from account_batch a left join account_template t on a.template_id = t.id order by source_system, template_id; # 2: Using filesort explain select a.source_system, a.template_id from account_batch a left join account_template t on a.template_id = t.id order by source_system, template_id, a.template_name;
- 前导列为常量,可以不满足最左前缀的要求。如下面的查询可以应用
(source_system、template_id、batch_no)
索引# Using where; Using index explain select source_system, batch_no from account_batch where source_system = 'JL_MANUAL_PRC' order by template_id, batch_no;