limit 10 offset 1000000为什么会很慢

一、前言

相信在后台开发得过程中,都会遇到分页问题,一般sql语句用limit实现分页。

一般刚开始学SQL的时候,会这样写:

SELECT * FROM table ORDER BY id LIMIT 1000, 10;

但在数据达到百万级的时候,这样写会慢死

SELECT * FROM table ORDER BY id LIMIT 1000000, 10;

也许耗费几十秒

二、查询慢原因

但是为什么数据量达到百万级别后分页会这么慢呢?

limit100 0000,20的意思扫描满足条件的1000020行,扔掉前面的1000000行,返回最后的20行,问题就在这里。一般得sql语句肯定不知一个limit函数,where条件还有很多负责得条件过滤,甚至分组,聚合函数等等,所以扫描满足条件得数据量太大,如果不采取优化得措施,一定会把你服务器卡死的。

LIMIT 451350,30 扫描了45万多行,怪不得慢的都堵死了。

但是limit 30 这样的语句仅仅扫描30行。

三、limit查询慢的优化

1、网上很多优化的方法是这样的

SELECT * FROM table WHERE id >= (SELECT id FROM table LIMIT 1000000, 1) LIMIT 10;

是的,速度提升到0.x秒了,看样子还行了
可是,还不是完美的!

以下这句才是完美的!

SELECT * FROM table WHERE id BETWEEN 1000000 AND 1000010;

比上面那句,还要再快5至10倍

另外,如果需要查询 id 不是连续的一段,最佳的方法就是先找出 id ,然后用 in 查询

SELECT * FROM table WHERE id IN(10000, 100000, 1000000...);


2、再举个例子:
日常分页SQL语句:
select id,name,content from users order by id asc limit 100000,20
扫描100020行

如果记录了上次的最大ID

select id,name,content from users where id>100073 order by id asc limit 20

扫描20行。

总数据有500万左右,以下例子

select * from users where name=‘张三’ order by id limit 300000,10 执行时间是 3.21s

优化后:

select * from (

select id from users

where name=‘张三’ order by id limit 300000,10

) a

left join users b on a.id=b.id

执行时间为 0.11s 速度明显提升

这里需要说明的是 我这里用到的字段是 name ,id 需要把这两个字段做复合索引,否则的话效果提升不明显。

四、总结

当一个数据库表过于庞大,LIMIT offset, length中的offset值过大,则SQL查询语句会非常缓慢,你需增加order by,并且order by字段需要建立索引。

如果使用子查询去优化LIMIT的话,则子查询必须是连续的,某种意义来讲,子查询不应该有where条件,where会过滤数据,使数据失去连续性。

如果你查询的记录比较大,并且数据传输量比较大,比如包含了text类型的field,则可以通过建立子查询。

sql示例:


SELECT id,title,content FROM items WHERE id IN (SELECT id FROM items ORDER BY id 
limit 900000, 10);  

如果limit语句的offset较大,你可以通过传递pk键值来减小offset = 0,这个主键最好是int类型并且auto_increment
sql示例:

  SELECT * FROM users WHERE uid > 456891 ORDER BY uid LIMIT 0, 10;

SELECT * FROM users WHERE uid >=  (SELECT uid FROM users ORDER BY uid limit 895682, 1) 
limit 0, 10;  

如果limit的offset值过大,用户也会翻页疲劳,你可以设置一个offset最大的,超过了可以另行处理,一般连续翻页过大,用户体验很差,则应该提供更优的用户体验给用户

复合索引:

开始的select id from collect order by id limit 90000,10; 这么快就是因为走了索引,可是如果加了where 就不走索引了。抱着试试看的想法加了 search(vtype,id) 这样的索引。然后测试

select id from collect where vtype=1 limit 90000,10; 非常快!0.04秒完成!

再测试: select id ,title from collect where vtype=1 limit 90000,10; 非常遗憾,8-9秒,没走search索引!

再测试:search(id,vtype),还是select id 这个语句,也非常遗憾,0.5秒。

综上:如果对于有where 条件,又想走索引用limit的,必须设计一个索引,将where 放第一位,limit用到的主键放第2位,而且只能select 主键!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Mysqloffset是用来指定查询结果集的起始行数的。通过设置offset可以跳过前面的若干行,从指定行数开始获取结果集,用于分页等场景。例如,查询文章列表时可以通过设置offsetlimit来实现分页的效果。 ### 回答2: MySQL中的OFFSET参数用于指定查询结果的偏移量,用于跳过前面的一些行,从而在查询结果中返回指定范围内的行。OFFSET的意义在于实现分页查询,例如在Web应用中显示大量数据的时候,可以将查询结果分页显示,每次只显示一部分数据,以提高性能和用户体验。 OFFSET参数的使用非常简便,通过将其与LIMIT一起使用,可以轻松地实现分页查询。假设希望每页显示10条数据,则可以设置LIMIT 10 OFFSET 0来获取第一页的数据,LIMIT 10 OFFSET 10来获取第二页的数据,以此类推。通过不断调整OFFSET的值,可以在查询结果中切割出所需的子集数据。 使用OFFSET参数的好处是可以灵活地控制查询结果的起始位置,可以方便地实现翻页功能。例如,用户可以点击页面上的“下一页”按钮,通过相应地调整OFFSET的值来获取下一页的数据。而且,OFFSET参数还能与其他查询条件结合使用,例如按照某个字段排序或添加其他条件限制等。 然而,使用OFFSET也需要注意一些问题。当偏移量非常大时,查询可能变得相对较慢,因为MySQL需要扫描并跳过要忽略的结果集。为了减少这种开销,可以考虑通过添加索引或使用其他优化技术来改进查询性能。此外,当数据发生变动时,例如删除了某些行,OFFSET值可能变得无效,因为数据的偏移位置改变。 综上所述,OFFSET参数在MySQL中的意义在于实现分页查询,使得在显示大量数据时可以分批加载,提高性能和用户体验。但需要注意其潜在的性能问题和数据变动的影响。 ### 回答3: MySQL中的OFFSET用于查询结果中跳过一定数量的行,而不是显示它们。OFFSET通常与LIMIT一起使用,LIMIT用于限制返回的行数,OFFSET用于指定从第几行开始返回结果。 OFFSET的意义在于对查询结果进行分页显示。例如,当我们需要从一个表中获取大量数据并进行分页显示时,可以使用OFFSET来指定每一页显示的数据量,从而实现分页功能。通过调整OFFSET的值,我们可以跳过前面的行数,显示接下来的数据。 假设我们有一个包含1000条记录的表格,我们想每页显示10条数据。如果我们不使用OFFSET,那么每次查询都返回全部1000条数据,显然效率很低。但使用OFFSET=0和LIMIT=10,我们只查询返回前10条数据,再使用OFFSET=10LIMIT=10查询,则返回接下来的10条数据,以此类推,实现了分页显示的功能。 除了分页显示外,OFFSET还可以用于更复杂的数据查询。例如,我们可以使用OFFSETLIMIT在查询结果中跳过一定数量的数据进行进一步的筛选和分析。 需要注意的是,使用OFFSET时要小心效率问题。随着OFFSET值的增加,查询的效率也逐渐下降,因为MySQL需要跳过多个行才能获取到指定的数据。因此,在处理大量数据时,最好使用其他优化方案来提高查询效率,而不是依赖OFFSET。 总而言之,OFFSETMySQL中的意义是实现查询结果的分页显示和数据筛选,通过跳过一定数量的行来获取需要的数据。但在使用时需注意效率问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初夏0811

你的鼓励将是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值