引言
在日志分析、最新数据展示等场景中,我们常需获取排序后的最后n条数据。传统思维认为直接使用order by ... desc limit n即可,但实测发现这种写法在大数据量下性能骤降。本文将深入解析mysql排序机制,揭秘高效获取最后10条数据的科学方法。
问题本质:排序与分页的矛盾
当执行select * from table order by id desc limit 10时,mysql需完成全量排序后再截取前10条。若表有百万级数据,即使只需最后10条,仍需处理全部数据。这种"先排序后截取"的机制导致:
- 索引覆盖失效,触发临时表创建
- 文件排序(filesort)消耗大量cpu/io
- 回表操作加剧随机io压力
解决方案:子查询+双重排序
1. 基础写法
select *
from (
select *
from stock_stock_day_data
where stock_code = '000001'
order by id desc
limit 10
) as sub
order by id asc;
2. 执行计划分析
通过explain可观察到:
- 内层查询使用索引
idx_stock_code_id完成倒序扫描 - 外层查询仅对10条结果进行正序排序
- 避免全表扫描(type=range)
- 消除using temporary/filesort
3. 性能对比
| 方案 | 执行时间 | 临时表 | 索引使用 |
|---|---|---|---|
| 直接排序 | 55s | 需创建 | 未使用复合索引 |
| 子查询法 | 0.055s | 无需 | 使用索引覆盖 |
性能优化进阶
1. 索引优化策略
- 复合索引设计:创建
(stock_code, id)索引,使内层查询直接利用索引排序 - 索引提示使用:
select * from ( select * from stock_stock_day_data force index (idx_stock_code_id) where stock_code = '000001' order by id desc limit 10 ) ...
- 覆盖索引优化:若查询字段固定,创建包含所有字段的复合索引
2. 执行计划调优
通过explain识别潜在问题:
type=all表示全表扫描,需优化索引extra=using filesort提示需优化排序字段索引rows值过大说明扫描数据过多
3. 服务器参数调整
- 增大
sort_buffer_size减少磁盘排序 - 调整
tmp_table_size避免临时表磁盘存储 - 优化
innodb_buffer_pool_size提升缓存命中率
特殊场景处理
1. 超大结果集优化
使用变量缓存法避免全量排序:
set @rownum := 0;
select *
from (
select *, @rownum := @rownum + 1 as rownum
from stock_stock_day_data
where stock_code = '000001'
order by id desc
) t1
where rownum <= 10
order by id asc;
2. 高并发场景优化
- 避免长事务导致的锁竞争
- 使用连接池控制并发度
- 分区表优化(按stock_code分区)
总结
高效获取最后10条数据需遵循"先定位后排序"原则:
- 使用子查询快速定位目标数据集
- 通过复合索引实现索引覆盖
- 外层查询仅对结果集进行二次排序
- 结合执行计划分析持续优化
通过索引优化、执行计划调优、服务器参数调整三管齐下,可使查询性能提升千倍。掌握这些核心方法,即可在百万级数据中实现毫秒级响应,真正实现"大数据,小延迟"的极致体验。
以上就是mysql排序机制之获取最后10条数据的正确方法的详细内容,更多关于mysql排序后取最后10条数据的资料请关注代码网其它相关文章!
发表评论