Mysql orderby limit 索引命中规则

本文记录了一次SQL慢查询优化的过程,涉及MySQL 5.6.25版本。通过案例分析,解释了当ORDER BY子句前有范围查询时,如何选择合适的索引来提高查询效率。建议在编写SQL时使用EXPLAIN来检查和优化,以减少扫描行数并减轻数据库负担。同时提出了在代码层处理分页的方法,以避免在SQL中使用LIMIT时的性能问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做的一个项目,发现了sql慢查询的情况,还好及时发现而且访问量并没有那么大,不然会造成很严重的事故,所以想记录一下,作为自己的成长记录,要不这脑子也不太好使记不住。

Mysql版本 5.6.25
表结构不展示啦 直接看索引 (公司的表不方便泄露 假如是table_name吧)
SHOW INDEX FROM table_name (列出索引信息)
在这里插入图片描述
问题sql (我是想通过questionId 进行排序 做分页处理 3475834代表上一页最大的questionId的值 )
EXPLAIN
SELECT QuestionID FROM table_name
WHERE (CourseSectionID in(569743,508457) )
AND (QuestionID > 3475834)
ORDER BY QuestionID
LIMIT 50

在这里插入图片描述
发现rows 的值有 60多万 就是mysql扫表行数有这么多 好恐怖(为什么恐怖自己查去 本节不介绍恐怖原因) 使用的索引是QuestionID和CourseSectionID 的联合索引

优化sql
1.EXPLAIN
SELECT QuestionID FROM table_name
WHERE

### 解析 MySQL 的 `LIMIT` 不使用索引的原因 当执行带有 `ORDER BY` 和 `LIMIT` 的查询时,如果存在合适的索引MySQL 应该能够高效地利用这些索引来加速查询。然而,在某些情况下,即使有可用的索引,性能仍然不佳。 主要原因是 MySQL 需要先按照指定列排序数据集,再应用 `LIMIT` 来获取前几条记录。这种操作模式可能导致大量随机读取,因为每次都需要通过索引找到对应的行位置并加载完整的数据页来验证条件匹配情况[^1]。 ```sql SELECT * FROM table_name WHERE condition ORDER BY column LIMIT offset, count; ``` 上述 SQL 查询会强制数据库引擎遍历整个表或部分分区的数据,并按给定字段排序之后才截取出所需数量的结果集。这使得即使是小范围内的检索也可能变得低效。 ### 如何优化以使 `LIMIT` 使用索引 为了提高此类查询效率,可以考虑以下几个方面: #### 创建覆盖索引(Covering Index) 创建一个包含所有需要返回字段在内的复合索引可以帮助减少回表次数。这样不仅减少了磁盘 I/O 开销,还提高了缓存命中率。 例如,对于如下查询: ```sql CREATE INDEX idx_cover ON table_name (creation_date, other_columns); ``` 这里的 `idx_cover` 是一个多列索引,它包含了用于排序的关键字 (`creation_date`) 及其他可能被 SELECT 子句请求到的列(`other_columns`) 。如此一来,只要满足一定条件下,MySQL 就可以直接从这个索引树中提取全部必要的信息而无需访问实际的数据文件[^3]。 #### 调整查询结构 有时重新设计查询逻辑也能带来显著改善。比如尝试将过滤条件提前处理掉一部分不符合要求的数据;或者采用子查询方式预先计算好偏移量(offset),从而降低主查询的工作负担。 另外值得注意的是,TokuDB 这样的存储引擎提供了更好的压缩算法和支持更复杂的事务特性,或许可以在特定场景下提供优于默认 InnoDB 表现的选择[^2]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值