排序
  cGIFZsDlOY2g 2023年11月02日 27 0
  • 问题
假设你的表里面已经有了 city_name(city, name) 这个联合索引,然后你要查杭州和苏州两个城市中所有的市民的姓名,并且按名字排序,显示前 100 条记录。如果 SQL 查询语句是这么写的 :

mysql> select * from t where city in ('杭州'," 苏州 ") order by name limit 100;
那么,这个语句执行的时候会有排序过程吗,为什么?
如果业务端代码由你来开发,需要实现一个在数据库端不需要排序的方案,你会怎么实现呢?
进一步地,如果有分页需求,要显示第 101 页,也就是说语句最后要改成 “limit 10000,100”, 你的实现方法又会是什么呢?
  • 分析
虽然有 (city,name) 联合索引,对于单个 city 内部,name 是递增的。但是由于这条 SQL 语句不是要单独地查一个 city 的值,而是同时查了"杭州"和" 苏州 "两个城市,因此所有满足条件的 name 就不是递增的了。也就是说,这条 SQL 语句需要排序。

那怎么避免排序呢?

这里,我们要用到 (city,name) 联合索引的特性,把这一条语句拆成两条语句,执行流程如下:

执行 select * from t where city=“杭州” order by name limit 100; 这个语句是不需要排序的,客户端用一个长度为 100 的内存数组 A 保存结果。

执行 select * from t where city=“苏州” order by name limit 100; 用相同的方法,假设结果被存进了内存数组 B。

现在 A 和 B 是两个有序数组,然后你可以用归并排序的思想,得到 name 最小的前 100 值,就是我们需要的结果了。

如果把这条 SQL 语句里“limit 100”改成“limit 10000,100”的话,处理方式其实也差不多,即:要把上面的两条语句改成写:

select * from t where city=" 杭州 " order by name limit 10100; 
和
select * from t where city=" 苏州 " order by name limit 10100。
这时候数据量较大,可以同时起两个连接一行行读结果,用归并排序算法拿到这两个结果集里,按顺序取第 10001~10100 的 name 值,就是需要的结果了。

当然这个方案有一个明显的损失,就是从数据库返回给客户端的数据量变大了。

所以,如果数据的单行比较大的话,可以考虑把这两条 SQL 语句改成下面这种写法:

select id,name from t where city=" 杭州 " order by name limit 10100; 
和
select id,name from t where city=" 苏州 " order by name limit 10100。
然后,再用归并排序的方法取得按 name 顺序第 10001~10100 的 name、id 的值,然后拿着这 100 个 id 到数据库中去查出所有记录。

上面这些方法,需要你根据性能需求和开发的复杂度做出权衡。
  • 参考答案
这条 SQL 语句需要排序
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  xaeiTka4h8LY   2024年05月31日   50   0   0 MySQLSQL
  xaeiTka4h8LY   2024年05月17日   54   0   0 数据库JavaSQL
  xaeiTka4h8LY   2024年05月17日   54   0   0 数据库SQL
  Dk8XksB4KnJY   2023年12月23日   32   0   0 字段字段SQLSQL
cGIFZsDlOY2g