我们以一个非聚簇索引为例,来分析一下 Limit 的影响。假设我们有一张表 test ,它有两个字段 id 和 val ,其中 id 是主键,val 是非唯一非聚簇索引。表中有 500 万条数据,val 的值从 1 到 10 随机分布。我们执行以下语句:
select * from test where val=4 limit 300000,5;
这条语句的意思是查询 val 等于 4 的记录,并返回第 300001 到第 300005 条记录。Mysql 会怎么执行呢?
扫描至少 300005 个索引页 访问至少 300005 次数据页 排序和过滤至少 300005 条数据记录
那么,有没有办法优化这个问题呢?
使用索引覆盖扫描。如果我们只需要查询部分字段,而不是所有字段,我们可以尝试使用索引覆盖扫描,也就是让查询所需的所有字段都在索引中,这样就不需要再访问数据页,减少了随机 I/O 操作。例如,如果我们只需要查询 id 和 val 字段,我们可以执行以下语句:
select id,val from test where val=4 limit 300000,5;
这样,Mysql 只需要扫描索引页,而不需要访问数据页,提高了查询效率。
使用子查询。如果我们不能使用索引覆盖扫描,或者查询字段较多,我们可以尝试使用子查询,也就是先用一个子查询找出我们需要的记录的 id 值,然后再用一个主查询根据 id 值获取其他字段。例如,我们可以执行以下语句:
select * from test where id in (select id from test where val=4 limit 300000,5);
这样,Mysql 先执行子查询,在 val 索引上进行范围扫描,并返回 5 个 id 值。然后,Mysql 再执行主查询,在 id 索引上进行点查找,并返回所有字段。这样,Mysql 只需要扫描 5 个数据页,而不是 300005 个数据页,提高了查询效率。
使用分区表。如果我们的表非常大,或者数据分布不均匀,我们可以尝试使用分区表,也就是将一张大表分成多个小表,并按照某个字段或者范围进行划分。这样,Mysql 可以根据条件只访问部分分区表,而不是整张表,减少了扫描和访问的数据量。例如,如果我们按照 val 字段将 test 表分成 10 个分区表(test_1 到 test_10),每个分区表只存储 val 等于某个值的记录,我们可以执行以下语句:
select * from test_4 limit 300000,5;
匿名
2025-10-22
盖楼盖楼!
匿名
2025-08-11
沙发沙发
匿名
2025-08-10
https://at.oiik.cn/bing.html
匿名
2025-02-21
实用,我在开发https://minmail.app/时候使用到了
王飞翔
2024-12-30
亲爱的朋友:您好!中国疫情持续蔓延,很多人症状非常严重持久不愈,医院人满为患,各年龄段随地倒猝死的现象暴增,多省感染手足口、甲流、乙流、支原体、合胞及腺病毒的儿童不断攀升,目前各种天灾人祸,天气异象频发。古今中外的很多预言都说了这几年人类有大灾难,如刘伯温在预言中说 “贫者一万留一千,富者一万留二三”,“贫富若不回心转,看看死期到眼前”, 预言中也告诉世人如何逃离劫难的方法,真心希望您能躲过末劫中的劫难,有个美好的未来,请您务必打开下方网址认真了解,内有躲避瘟疫保平安的方法。网址1:https://github.com/1992513/www/blob/master/README.md?abhgc#1 网址2:bitly.net/55bbbb 网址3:https://d3ankibxiji86m.cloudfront.net/30gj 如打不开请多换几个浏览器试
匿名
2024-12-12
Backdata 搜索引擎网址提交入口:https://backdata.net/submit-site.html