一般我们通常会order by limit start ,offset的方式进行分页查询。
1一般而言,分页sql的耗时随着start的增加而急剧的增加
例如:select * from a1 limit 100,10 --->0.02s
select * from a1 limit 100000,10--->3.02s
可以看出,随着start的急剧增加,耗时成倍的增加,如何优化呢?
一般想要优化分页,最好的解决办法就是:没有分页。或者可以把分页的算法给Sphinx,Lucence等第三方解决方案。没有必要让mysql做它不擅长的事情。
limit 100,10-->mysql查询计划是row是110行,limit 100000,10,row是100010,速度慢就可想而知了,
思路:
1.尽可能直接从索引中获取数据,减少扫描行数据的频率。(索引覆盖)
2.尽可能减少扫描的记录的数量,也就是先确定起始的范围,再往后取n条记录就行。
解决:
1子查询的方式:在子查询中,先从索引找到最大的Id,然后倒排序去10行。
索引找最大的ID,用了索引覆盖,速度很快,找到最大ID,where id<maxid limit 10,但是要注意一点,子查询用的是All,例如:select .....where id in(select id .....);子查询是在主表里全表扫描,然后再与子表进行匹配,所以一般慎用子查询。
2inner join
select id from a1 limit 100000,10-->用索引覆盖取到主键ID,inner join 连表查询
最好还是用inner join
3.测试 不带where
explain select * from tr_outdb_16_05 order by id desc limit 100000,10(616ms)
3.1 子查询方式:select * from (select * from tr_outdb_16_05 where id >(select id from tr_outdb_16_05 order by id desc limit 100000,1) limit 10) t order by id desc (137ms)
3.2 innerjoin :select * from tr_outdb_16_05 inner join (select id from tr_outdb_16_05 order by id desc limit 100000,10) tt on tt.id=tr_outdb_16_05.id (131ms)
这是数据量还是比较少的,尤其是针对大分页的情况,优先采用inner join的方法。