MYSQL分页limit速度太慢的优化方法_Mysql

在mysql中limit可以实现快速分页,但是如果数据到了几百万时我们的limit必须优化才能有效的合理的实现分页了,否则可能卡死你的服务器哦。

   当一个表数据有几百万的数据的时候成了问题!

   如 * from table limit 0,10 这个没有问题 当 limit 200000,10 的时候数据读取就很慢,可以按照一下方法解决
    第一页会很快
   PERCONA PERFORMANCE CONFERENCE 2009上,来自雅虎的几位工程师带来了一篇”EfficientPagination Using MySQL”的报告
   limit10000,20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行,问题就在这里。
   LIMIT 451350 , 30 扫描了45万多行,怪不得慢的都堵死了。
   但是
   limit 30 这样的语句仅仅扫描30行。

   那么如果我们之前记录了最大ID,就可以在这里做文章

   举个例子

   日常分页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 wl_tagindex where byname='f' order by id limit 300000,10 执行时间是 3.21s
   优化后:

 select * from (
    select id from wl_tagindex
    where byname='f' order by id limit 300000,10
 ) a
 left join wl_tagindex b on a.id=b.id

   执行时间为 0.11s 速度明显提升
   这里需要说明的是 我这里用到的字段是 byname ,id 需要把这两个字段做复合索引,否则的话效果提升不明显

   总结

   当一个数据库表过于庞大,LIMIT offset, length中的offset值过大,则SQL查询语句会非常缓慢,你需增加order by,并且order by字段需要建立索引。
   如果使用子查询去优化LIMIT的话,则子查询必须是连续的,某种意义来讲,子查询不应该有where条件,where会过滤数据,使数据失去连续性。
   如果你查询的记录比较大,并且数据传输量比较大,比如包含了text类型的field,则可以通过建立子查询。

   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

   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最大的,超过了可以另行处理,一般连续翻页过大,用户体验很差,则应该提供更优的用户体验给用户。

   limit 分页优化方法

   1.子查询优化法
   先找出第一条数据,然后大于等于这条数据的id就是要获取的数据
   缺点:数据必须是连续的,可以说不能有where条件,where条件会筛选数据,导致数据失去连续性
   实验下
    mysql> set profi=1;
   Query OK, 0 rows affected (0.00 sec)
   mysql> select count(*) from Member;
   +———-+
   | count(*) |
   +———-+
   |   169566 |
   +———-+
   1 row in set (0.00 sec)
   mysql> pager grep !~-
   PAGER set to ‘grep !~-‘
   mysql> select * from Member limit 10, 100;
   100 rows in set (0.00 sec)
   mysql> select * from Member where MemberID >= (select MemberID from Member limit 10,1) limit 100;
   100 rows in set (0.00 sec)
   mysql> select * from Member limit 1000, 100;
   100 rows in set (0.01 sec)
   mysql> select * from Member where MemberID >= (select MemberID from Member limit 1000,1) limit 100;
   100 rows in set (0.00 sec)
   mysql> select * from Member limit 100000, 100;
   100 rows in set (0.10 sec)
   mysql> select * from Member where MemberID >= (select MemberID from Member limit 100000,1) limit 100;
   100 rows in set (0.02 sec)
   mysql> nopager
   PAGER set to stdout
   mysql> show profilesG
   *************************** 1. row ***************************
   Query_ID: 1
   Duration: 0.00003300
      Query: select count(*) from Member
   *************************** 2. row ***************************
   Query_ID: 2
   Duration: 0.00167000
      Query: select * from Member limit 10, 100
   *************************** 3. row ***************************
   Query_ID: 3
   Duration: 0.00112400
      Query: select * from Member where MemberID >= (select MemberID from Member limit 10,1) limit 100
   *************************** 4. row ***************************
   Query_ID: 4
   Duration: 0.00263200
      Query: select * from Member limit 1000, 100
   *************************** 5. row ***************************
   Query_ID: 5
   Duration: 0.00134000
      Query: select * from Member where MemberID >= (select MemberID from Member limit 1000,1) limit 100
   *************************** 6. row ***************************
   Query_ID: 6
   Duration: 0.09956700
      Query: select * from Member limit 100000, 100
   *************************** 7. row ***************************
   Query_ID: 7
   Duration: 0.02447700
      Query: select * from Member where MemberID >= (select MemberID from Member limit 100000,1) limit 100
    从结果中可以得知,当偏移1000以上使用子查询法可以有效的提高性能。
   2.倒排表优化法
   倒排表法类似建立索引,用一张表来维护页数,然后通过高效的连接得到数据
   缺点:只适合数据数固定的情况,数据不能删除,维护页表困难
   3.反向查找优化法
   当偏移超过一半记录数的时候,先用排序,这样偏移就反转了
   缺点:order by优化比较麻烦,要增加索引,索引影响数据的修改效率,并且要知道总记录数
   ,偏移大于数据的一半
   引用
   limit偏移算法:
   正向查找: (当前页 – 1) * 页长度
   反向查找: 总记录 – 当前页 * 页长度
   做下实验,看看性能如何
   总记录数:1,628,775
   每页记录数: 40
   总页数:1,628,775 / 40 = 40720
   中间页数:40720 / 2 = 20360
   第21000页
   正向查找SQL:
   Sql代码
   SELECT * FROM `abc` WHERE `BatchID` = 123 LIMIT 839960, 40
   时间:1.8696 秒
   反向查找sql:
   Sql代码
   SELECT * FROM `abc` WHERE `BatchID` = 123 ORDER BY InputDate DESC LIMIT 788775, 40
   时间:1.8336 秒
   第30000页
   正向查找SQL:
   Sql代码
   1.SELECT * FROM `abc` WHERE `BatchID` = 123 LIMIT 1199960, 40
   SELECT * FROM `abc` WHERE `BatchID` = 123 LIMIT 1199960, 40
   时间:2.6493 秒
   反向查找sql:
   Sql代码
   1.SELECT * FROM `abc` WHERE `BatchID` = 123 ORDER BY InputDate DESC LIMIT 428775, 40
   SELECT * FROM `abc` WHERE `BatchID` = 123 ORDER BY InputDate DESC LIMIT 428775, 40
    时间:1.0035 秒
   注意,反向查找的结果是是降序desc的,并且InputDate是记录的插入时间,也可以用主键联合索引,但是不方便。
   4.limit限制优化法
   把limit偏移量限制低于某个数。。超过这个数等于没数据,我记得alibaba的dba说过他们是这样做的
   5.只查索引法

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索mysql
, limit
分页优化
mysql limit分页优化、sql limit 分页优化、mysql limit 分页、mysql limit分页查询、php mysql limit 分页,以便于您获取更多的相关知识。

时间: 2024-10-31 23:16:47

MYSQL分页limit速度太慢的优化方法_Mysql的相关文章

MYSQL分页limit速度太慢优化详解

在mysql中limit可以实现快速分页,但是如果数据到了几百万时我们的limit必须优化才能有效的合理的实现分页了,否则可能卡死你的服务器哦. 当一个表数据有几百万的数据的时候成了问题! 如 * from table limit 0,10 这个没有问题 当 limit 200000,10 的时候数据读取就很慢,可以按照一下方法解决 第一页会很快 PERCONA PERFORMANCE CONFERENCE 2009上,来自雅虎的几位工程师带来了一篇"EfficientPagination Us

MYSQL分页limit速度太慢优化方法

当一个表数据有几百万的数据时,分页的时候成了问题 如 select * from table limit 0,10 这个没有问题 当 limit 200000,10 的时候数据读取就很慢,可以按照一下方法解决 最近一个网站的服务器评论被人刷死,导致mysql数据库异常发生too many open connections 引发的SQL语句  代码如下 复制代码 SELECT a.uid, a.veil, a.content, a.datetimes, a.audit, b.user_name,

mysql关联子查询的一种优化方法分析_Mysql

本文实例讲述了mysql关联子查询的一种优化方法.分享给大家供大家参考,具体如下: 很多时候,在mysql上实现的子查询的性能较差,这听起来实在有点难过.特别有时候,用到IN()子查询语句时,对于上了某种数量级的表来说,耗时多的难以估计.本人mysql知识所涉不深,只能慢慢摸透个中玄机了. 假设有这样的一个exists查询语句: select * from table1 where exists (select * from table2 where id>=30000 and table1.u

mysql优化limit查询语句的5个方法_Mysql

mysql的分页比较简单,只需要limit offset,length就可以获取数据了,但是当offset和length比较大的时候,mysql明显性能下降 1.子查询优化法 先找出第一条数据,然后大于等于这条数据的id就是要获取的数据 缺点:数据必须是连续的,可以说不能有where条件,where条件会筛选数据,导致数据失去连续性,具体方法请看下面的查询实例: 复制代码 代码如下: mysql> set profiling=1; Query OK, 0 rows affected (0.00

MySQL分页原理技术整理的8个方法

下面是本人总结整理的Mysqy的分页原理,喜欢对分页性能优化的朋友可以参考学习. 方法1: 直接使用数据库提供的SQL语句 ---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N. ---适应场景: 适用于数据量较少的情况(元组百/千级). ---原因/缺点: 全表扫描,速度会很慢 且 有的数据库结果集返回不稳定(如某次返回1,2,3,另外的一次返回2,1,3).Limit限制的是从结果集的M位置处取出N条输出,其余抛弃. 方法2: 建立主键或唯一

MySQL Order By索引优化方法_Mysql

尽管 ORDER BY 不是和索引的顺序准确匹配,索引还是可以被用到,只要不用的索引部分和所有的额外的 ORDER BY 字段在 WHERE 子句中都被包括了. 使用索引的MySQL Order By 下列的几个查询都会使用索引来解决 ORDER BY 或 GROUP BY 部分: 复制代码 代码如下: SELECT * FROM t1 ORDER BY key_part1,key_part2,... ; SELECT * FROM t1 WHERE key_part1=constant ORD

MySQL中对表连接查询的简单优化教程_Mysql

在MySQL中,A LEFT JOIN B join_condition执行过程如下: · 根据表A和A依赖的所有表设置表B. · 根据LEFT JOIN条件中使用的所有表(除了B)设置表A. · LEFT JOIN条件用于确定如何从表B搜索行.(换句话说,不使用WHERE子句中的任何条件). · 可以对所有标准联接进行优化,只是只有从它所依赖的所有表读取的表例外.如果出现循环依赖关系,MySQL提示出现一个错误. · 进行所有标准WHERE优化. · 如果A中有一行匹配WHERE子句,但B中没

mysql简单实现查询结果添加序列号的方法_Mysql

本文实例讲述了mysql简单实现查询结果添加序列号的方法.分享给大家供大家参考,具体如下: 第一种方法: 复制代码 代码如下: select (@i:=@i+1) as i,table_name.* from table_name,(select @i:=0) as it 第二种方法: set @rownum=0; select @rownum:=@rownum+1 as rownum, t.username from auth_user t limit 1,5; 更多关于MySQL相关内容感兴

MySQL查看、创建和删除索引的方法_Mysql

本文实例讲述了MySQL查看.创建和删除索引的方法.分享给大家供大家参考.具体如下: 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术,能够大大提高查询效率.特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍. 例如,有3个未索引的表t1.t2.t3,分别只包含列c1.c2.c3,每个表分别含有1000行数据组成,指为1-1000的数值,查找对应值相等行的查询如下所示. SELECT c1,c2,c3 FROM t1,t2,t3