Home  >  Article  >  Database  >  使用子查询提高MySQL分页效率 limit

使用子查询提高MySQL分页效率 limit

WBOY
WBOYOriginal
2016-06-07 15:47:011225browse

1.LIMITn等价于LIMIT0,n偏移offset较小的时候,直接使用limit较优。 2、offset大的时候。 select * from yanxue8_visit limit 10000,10 多次运行,时间保持在0.0187左右 Select * From yanxue8_visit Where vid =( Select vid From yanxue8_visit Order By v

 

1.LIMIT n 等价于 LIMIT 0,n 偏移offset较小的时候,直接使用limit较优。

2、offset大的时候。
select * from yanxue8_visit limit 10000,10
多次运行,时间保持在0.0187左右

Select * From yanxue8_visit Where vid >=(
Select vid From yanxue8_visit Order By vid limit 10000,1
) limit 10
多次运行,时间保持在0.0061左右,只有前者的1/3。可以预计offset越大,后者越优

性能优化:基于MySQL5.0中limit的高性能,我对数据分页也重新有了新的认识.

1.
Select * From cyclopedia Where ID>=(Select Max(ID) From (Select ID From cyclopedia Order By ID limit90001) As tmp) limit 100;
2.
Select * From cyclopedia Where ID>=(Select Max(ID) From ( Select ID From cyclopedia Order By ID limit90000,1) As tmp) limit 100;

同样是取90000条后100条记录,第1句快还是第2句快?
第1句是先取了前90001条记录,取其最大ID值作为起始,然后快速定位下100条记录
第2句择是仅仅取90000条记录后1条,然后取ID值作起始标识定位下100条记录
很明显第2句胜出.看来limit好像并不完全像我之前想象的那样做全表扫描返回limit offset+length条记录,这样看来limit比起MS-SQL的Top性能还是要提高不少的.


可是,既然MySQL有limit可以直接控制取出记录的位置,为什么不干脆用Select * From cyclopedia limit90000,1呢?  岂不更简洁?
这样想就错了,试了就知道,结果是:1 row in set (8.88)sec,怎么样,够吓人的吧,让我想起了昨天在4.1中比这还有过之的"高分" .Select *最好不要随便用,要本着用什么,选什么的原则, Select的字段越多,字段数据量越大,速度就越慢.上面2种分页方式哪种都比单写这1句强多了,虽然看起来好像查询的次数更多一些,但实际上是以较小的代价换取了高效的性能,是非常值得的.

靠主键ID来定位起始段总是最快
但不管是实现方式是存贮过程还是直接代码中,瓶颈始终在于MS-SQL的TOP总是要返回前N个记录,这种情况在数据量不大时感受不深,但如果成百上千万,效率肯定会低下的.相比之下MySQL的limit就有优势的多,执行:

LIMIT 思考

 

PERCONA PERFORMANCE CONFERENCE 2009上,来自雅虎的几位工程师带来了一篇”EfficientPagination Using MySQL“的报告,有很多亮点,本文是在原文基础上的进一步延伸。首先看一下分页的基本原理:

limit10000,20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行,问题就在这里,如果是limit100000,100,需要扫描100100行,在一个高并发的应用里,每次查询需要扫描超过10W行,性能肯定大打折扣。文中还提到limit n性能是没问题的,因为只扫描n行。

文中提到一种”clue”的做法,给翻页提供一些”线索”,比如还是SELECT * FROM message ORDER BYidDESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500

SELECT * FROM message WHERE id > 9527 ORDER BYid ASC LIMIT 20;

SELECT * FROM message WHERE id

不管翻多少页,每次查询只扫描20行。

如果LIMIT m,n不可避免的话,要优化效率,只有尽可能的让m小一下,我们扩展前面的”clue”做法,还是SELECT *FROM message ORDER BY idDESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500,比如要跳到第8页,我看的SQL语句可以这样写:

SELECT * FROM message WHERE id > 9527 ORDER BYid ASC LIMIT 20,20;

跳转到第13页:

SELECT * FROM message WHERE id

原理还是一样,记录住当前页id的最大值和最小值,计算跳转页面和当前页相对偏移,由于页面相近,这个偏移量不会很大,这样的话m值相对较小,大大减少扫描的行数。其实传统的limitm,n,相对的偏移一直是第一页,这样的话越翻到后面,效率越差,而上面给出的方法就没有这样的问题。

注意SQL语句里面的ASC和DESC,如果是ASC取出来的结果,显示的时候记得倒置一下。已在60W数据总量的表中测试,效果非常明显。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn