优化LIMIT分页

在系统中需要分页的操作通常会使用limit加上偏移量的方法实现,同时加上合适的order by 子句。如果有对应的索引,通常效率会不错,否则MySQL需要做大量的文件排序操作。

一个非常令人头疼问题就是当偏移量非常大的时候,例如可能是limit 10000,20这样的查询,这是mysql需要查询10020条然后只返回最后20条,前面的10000条记录都将被舍弃,这样的代价很高。如果所有的页面被访问的频率相同,那么这样的查询平均需要访问半个表的数据。要优化这样的查询,要么实在页面中限制分页的数量,要么是优化大偏移量的性能。

优化此类查询的一个最简单的方法是尽可能的使用索引覆盖扫描,而不是查询所有的列。然后根据需要做一次关联操作再返回所需的列。对于偏移量很大的时候这样做的效率会得到很大提升。对于下面的查询:

Select id, description from news order by title limit 50,5;

如果这个表非常大,那么这个查询可以改写成如下的方式:

Select news.id, news.description from news inner join (select id from news order by title limit 50,5) as myNew using(id);

这里的“延迟关联”将大大提升查询的效率,它让MySQL扫描尽可能少的页面,获取需要的记录后再根据关联列回原表查询需要的所有列。这个技术也可以用在优化关联查询中的limit。

Limit和offset的问题其实是offset的问题,它会导致MySQL扫描大量不需要的行然后再抛弃。如果可以使用书签记录上次取数据的位置,那么下次就可以直接从该位置开始扫描,这样可以避免使用offset。例如:

Select id, description from news where id >10000 limit 5;这样做的好处是无论翻页到多么后面,其性能都会很好。

其他优化的办法还包括使用预先计算的汇总表,或者关联一个冗余表,冗余表只需要包含主键列和需要排序的数据列。还可以使用Sphinx优化一些搜索操作。

还有一种做法就是做数据缓存。先获得并缓存较多的数据,例如,缓存一千条,然后每次分页都从这个缓存中获得。

关于分页的总条数:

分页的时候另一个常用的技巧是在LIMIT语句中加上SQL_CALL_FOUND_ROWS提示(即hint),这样就可以获得去掉limit以后满足条件的行数,因此可以作为分页的总行数。但实际上MySQL只有在扫描了满足条件的所有行后才知道总行数。所以加上这个提示之后不管需不需要都会扫描所有的行,然后再抛弃掉不需要的行,而不是在满足limit的行数后就终止扫描。所以该提示的代价可能非常高。

有时候也可以考虑EXPLAIN的结果中的rows列的值作为结果集总数的近似值(实际上Google的搜索结果也是个近似值)。当需要精确的结果的时候再单独使用COUNT(*)来满足需求。

不过可以查询一次总行数并缓存起来,这样就不用每次都查询一下总行数了。

时间: 2024-10-03 22:49:53

优化LIMIT分页的相关文章

mysql优化limit分页

mysql limit分页优化

近期一个项目遇到mysql limit分页奇慢无比,查看了数量也就一百万左右,可是查询的一页数据需要两分多钟,sql语句大约是order by limit,网上的优化大概都是在索引,优化子查询这类,都一一试过,速度并没有大的提升. 后来脑洞大开,是不是order by的问题,想想一百万条数据排序应该也是很耗时间的,于是将order by删除了,果然两分半钟竟然缩短到了0.045秒.经过测试如果是单个表的查询,order by 对速度的影响不太明显,当查询和关联和子查询的时候,对速度的影响就显而易

mysql limit分页优化方法分享

MySQL的优化是非常重要的.其他最常用也最需要优化的就是limit.MySQL的limit给分页带来了极大的方便,但数据量一大的时候,limit的性能就急剧下降. 同样是取10条数据 select * from yanxue8_visit limit 10000,10 和 select * from yanxue8_visit limit 0,10 就不是一个数量级别的. 网上也很多关于limit的五条优化准则,都是翻译自MySQL手册,虽然正确但不实用.今天发现一篇文章写了些关于limit优

MYSQL 分页慢加速器 解决方案 MYSQL 分页优化 MYSQL 分页解决方案 LIMIT 优化

无论你是InnoD引擎LIMIT分页慢还是MyISAM引擎LIMIT分页慢,大伙SELECT查询分页一般都是这样的[数据总共2万条,需要查询3个字段]: SELECT `id` , `url` , `content` FROM `product` WHERE 1 ORDER BY `id` LIMIT 10000 , 100 执行速度是: 45.7秒 哈哈,慢的掉渣吧! 作者LET再次隆重推荐 MySql LIMIT 分页查询加速利器解决方案: http://my.oschina.net/car

正确使用索引(sql优化),limit分页优化,执行计划,慢日志查询

查看表相关命令 - 查看表结构   desc 表名- 查看生成表的SQL   show create table 表名- 查看索引   show index from  表名 使用索引和不使用索引 由于索引是专门用于加速搜索而生,所以加上索引之后,查询效率会快到飞起来. # 有索引 mysql> select * from tb1 where name = 'zhangqiye'; +-----+-------------+---------------------+--------------

SQL通用优化方案(where优化、索引优化、分页优化、事务优化、临时表优化)

SQL通用优化方案:1. 使用参数化查询:防止SQL注入,预编译SQL命令提高效率2. 去掉不必要的查询和搜索字段:其实在项目的实际应用中,很多查询条件是可有可无的,能从源头上避免的多余功能尽量砍掉,这是最简单粗暴的解决方案.3. 选择最有效率的表名顺序: 数据库的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表放在最后,如果有3个以上的表连接查询,那就需要选择那个被其他表所引用的表放在最后.

mysql通过“延迟关联”进行limit分页查询优化的一个实例

最近在生产上遇见一个分页查询特别慢的问题,数据量大概有200万的样子,翻到最后一页性能很低,差不多得有4秒的样子才能出来整个页面,需要进行查询优化. 第一步,找到执行慢的sql,如下: SELECT         shotel_id as hotelId, mroom_type_id as mroomTypeId, available_date as availableDate, result_status as resultStatus, create_time as createTime,

MySQL---正确使用索引、limit分页、执行计划、慢日志查询

正确使用索引 数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效.即使建立索引,索引也不会生效: 1 - like '%xx' 2 select * from tb1 where name like '%cn'; 3 - 使用函数 4 select * from tb1 where reverse(name) = 'wupeiqi'; 5 - or 6 select * from tb1 where nid = 1 or e

如何优化limit

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