mysql Order By所引发的
2019-01-22 本文已影响0人
lionel880
生产接到公司运营的反馈,部分数据丢失,由于程序已经稳定运行了1年多,没想到sql语句还隐藏着坑。
问题的定位和复现目前都很清楚了,别人的文章也写得很清楚,我这就是简单在整理一下思路
参考文章:
MySQL使用order by + limit语句的坑
MySQL排序内部原理探秘
外部排序
1、问题的表现
数据的刷入有缺失,但程序无报错。最终怀疑是sql查询的时候数据本身有缺失。
sql 排序后,每次取一部分数据,但排序字段为跟新时间,此字段并没有添加索引
select * from tbl order by upd_ts limit n offset m
每次都不断的增加offset
2、基础知识储备
2.1外部排序
关于外部排序,可以参考外部排除的参考文献,了解外部排序的基本方法
- 基础方案
外部排序,之所以需要是因为数据的规模超过了内存的限制。所以基础的思路是通过分而治之的思路,将数据进行先拆分,在归并排序。
最基础的就是方案:快排+归并 - 优化
这个基础上,优化总的思路就一个,减少归并的次数
减少归并的次数方法:
1.每一个段分大一点:通过小根堆置换选择排序生成段
这个扫雪机模型理解了很多,才理解为什么平均为2倍,有空得专门写一篇
2.相同的段数合并次数减少:多路归并
2.2 mysql的排序
mysql的排序会在order by,group by 等语法中被使用,其中limit的大小也会影响算法,详细可以看参考文献的《[MySQL排序内部原理探秘》
- 排序字段如果是索引
事情就会很少,只需要根据 B-tree找到第一个,然后依次去过去就行。特别注意,就算是使用索引字段进行排序,也不意味着真的就使用了索引,可以通过 explain进行分析。mysql内部会优化,当字段过长时,可能会是全表扫描排序更快,这个要注意,有参数进行调节 - 排序字段如果是不是
大致思路就是先找出结果,再排序,再选出相应数量limit返回
mysql 的排序重复值的随机性来源有很多,由于没有了解源码,只能做猜测性分析
1.快排的不稳定性
2.limit导致的优先级队列优化,内部堆排序的不稳定性