mysql分页就直接使用limit进行操做,limit若是咱们直接不加任何处理可能数据大了就会很卡的。php
一. 最多见MYSQL最基本的分页方式:mysql
select * from content order by id desc limit 0, 10web
在中小数据量的状况下,这样的SQL足够用了,惟一须要注意的问题就是确保使用了索引。随着数据量的增长,页数会愈来愈多,查看后几页的SQL就可能相似:sql
select * from content order by id desc limit 10000, 10性能优化
一言以蔽之,就是越日后分页,LIMIT语句的偏移量就会越大,速度也会明显变慢。并发
MYSQL分页性能优化高并发
limit 10000,20的意思扫描知足条件的10020行,扔掉前面的10000行,返回最后的20行,问题就在这里,若是是limit 100000,100,须要扫描100100行,在一个高并发的应用里,每次查询须要扫描超过10W行,性能确定大打折扣。文中还提到limit n性能是没问题的,由于只扫描n行。性能
文中提到一种”clue”的作法,给翻页提供一些”线索”,好比仍是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500,若是咱们只提供”上一页”、”下一页”这样的跳转(不提供到第N页的跳转),那么在处理”上一页”的时候SQL语句能够是:测试
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20;优化
无论翻多少页,每次查询只扫描20行。
缺点是只能提供”上一页”、”下一页”的连接形式,可是咱们的产品经理很是喜欢”<上一页 1 2 3 4 5 6 7 8 9 下一页>”这样的连接方式,怎么办呢?
若是LIMIT m,n不可避免的话,要优化效率,只有尽量的让m小一下,咱们扩展前面的”clue”作法,仍是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500,好比要跳到第8页,我看的SQL语句能够这样写:
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20,20;
跳转到第13页:
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 40,20;
还有网友说可使用子查询来操做
一,子查询的分页方式来提升分页效率,飘易用的SQL语句以下:
代码以下复制代码SELECT * FROM `content` WHERE id <=
(SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) ORDER BY id desc LIMIT $pagesize
为何会这样呢?由于子查询是在索引上完成的,而普通的查询时在数据文件上完成的,一般来讲,索引文件要比数据文件小得多,因此操做起来也会更有效率。(via)经过explain SQL语句发现:子查询使用了索引!
代码以下复制代码id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY content range PRIMARY PRIMARY 4 NULL 6264 Using where
2 SUBQUERY content index NULL PRIMARY 4 NULL 27085 Using index
通过飘易的实测,使用子查询的分页方式的效率比纯LIMIT提升了14-20倍!
二,JOIN分页方式
代码以下复制代码SELECT * FROM `content` AS t1
JOIN (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) AS t2
WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;
通过个人测试,join分页和子查询分页的效率基本在一个等级上,消耗的时间也基本一致。explain SQL语句:
代码以下复制代码id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 6264 Using where
2 DERIVED content index NULL PRIMARY 4 NULL 27085 Using index