MySql深度分页慢sql原因

先说解决方案:索引排序+索引覆盖+延迟关联。

比如查询语句如下:

select * from user order by  createTime limit 500000, 10;

 延迟关联,即先查主键 id,然后根据 id 查其它字段:

select * from user u,(select id from user order by createTime  limit 500000, 10) t where u.id=t.id;

 详细原理如下:

随着 mysql limit 的值越来越大,查询可能慢,比如:

select * from user order by createTime  limit 500000 , 10;

慢的真正原因,不是因为扫描了 500000 行,而在于把这 500000 行数据重新排序。

explain 如下:

 可以看到 Extra 是 Using filesort,表示外部排序,

 索引有两个功能:查找和排序。

大家一般对索引的查找功能比较了解,却忽视了索引的排序功能,索引中的数据是已经排好序的,如果从索引中拿到的数据顺序跟我们需要排序的顺序是一致的,那就不要重新排序了。

怎么解决 Using filesort 呢?答案是给order by 后面列使用索引; 

select * from user order by  id limit 500000, 10;  --270ms


 延迟关联:

延迟关联就是指先拿到主键 id,然后再根据 id 查询 select *

select id from user order by id limit 500000, 10;

 Extra 的中 Using index 就表示“覆盖索引”,表示整个查询过程仅读取了索引中的数据而没有回表查询。

合并在一个 sql 语句中:

select * from user u,(select id from user order by id limit 500000, 10)  t where u.id=t.id; --83ms


索引覆盖:

mysql B+树索引:

  mysql 的主键索引叶字节点存的是主键所对应行的整行的全量数据

使用索引覆盖后查询:

select * from user order by id limit 500000, 10;  --305ms  all

select id from user order by id limit 500000, 10;  --99ms   index

重排序查询:

select * from user order by id limit 500000, 10;  --305ms  all

select * from user order by createTime limit 500000, 10;  --999ms  all filesort

 可以发现在50w条数据时, 即使是全表扫描, 0.3s, 索引覆盖0.1s

如果使用非索引字段排序, 则0.9s


总结: 

mysql深度分页问题的根因,不是因为扫描了大量数据,而是大量数据的重新排序太耗时,只要不重排序,就算扫描了大量数据,也不会有性能问题。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL中的深度分页查询指的是在大数据量情况下,需要从结果集中获取指定页码的数据。由于使用传统的LIMIT和OFFSET方式进行分页查询可能会导致性能问题,MySQL提供了一种优化的方法来处理深度分页查询,即使用游标(Cursor)。 以下是使用游标实现深度分页查询的步骤: 1. 使用DECLARE语句定义一个游标,并指定查询语句。例如: ```sql DECLARE cursor_name CURSOR FOR SELECT * FROM your_table ORDER BY column_name; ``` 这里的your_table是要查询的表名,column_name是用于排序的列名。 2. 使用OPEN语句打开游标,并设置偏移量。例如: ```sql OPEN cursor_name; SET @offset = (page_number - 1) * page_size; ``` 这里的page_number是要查询的页码,page_size是每页的数据量。 3. 使用FETCH语句获取指定偏移量的数据。例如: ```sql FETCH cursor_name FROM cursor_name INTO @column1, @column2, ...; ``` 这里的@column1, @column2, ...是用于存储查询结果的变量。 4. 使用CLOSE语句关闭游标。例如: ```sql CLOSE cursor_name; ``` 5. 最后,可以将获取到的数据进行处理和展示。 需要注意的是,游标方式适用于大数据量下的深度分页查询,但也有一些限制和注意事项: - 游标会占用数据库的资源,因此使用完毕后需要及时关闭。 - 如果表的数据发生变化,游标查询的结果可能不准确。 - 游标方式适用于MySQL 5.5及以上版本。 希望以上信息对你有所帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值