最近我们的一个项目,由于一次请求满足条件数据库的数据量过于大,所以页面的访问很是缓慢,现在在做优化就是一次只请求一页数据过来,当用户点击下一页或者上一页或者进入指定的页就会立即去请求这样会很快,可以极大的提高速度。
由于我们的数据库用的是mysql,故而一般使用的limit start,count来进行分页请求,这样的请求看似是极好的,但是当我们的数据量很大的时候,到达几百万的情况下,找最后一页的数据的的速率会下降,就是start 数值越大,我们的效率就月底。
1统计所有的条数 .
被我们的cpu_statistic表有3百多万条数据,
终端在线统计表里面没有数据
可以看到数据量越大,统计的时间就越长(统计所得,三百多万条,耗时0.7秒,五百多万条,耗时就达到了10秒多)。
2. limit分页优化
1). 查询前三条数据,速度极快:
这个是根据id降序排列
这个是没有排序,默认是升序的
可以看得到查询的数据还是极快的,
2).查询倒数两条数据,就可以看得到最起码要花掉1秒的时间
首先我们可以看得到,上图有两种方法,
第一种方法,最原始的limit start,count 花了1.78秒,可以看到随着start的增大时间变长了,原因是mysql要扫描前3407870条数据及以后的三天,然后把前3407870条记录给抛弃了。
第二种方法,直接查找从哪儿开始开始的3条记录,id直接判断,调过了全部扫描的过程,所以更快,且随着数据增长速度会更快
下面还有第三种方法,内连接,运行效果如下:
可以看得出效果也是比最原始的limit start,count变快了,但是效果比第二种方法慢一点,但也差不了多少,所以我推荐使用第二种方法。
总结下来就是优化limit有两种方法:
-
子查询
-
内连接
3.分页的limit之前如果不加上order by语句,查询时间就会缩短。
可以看得到每条语句比不加order by要快上400多毫秒。
4.详细的解释分页优化子查询的语句的意思(新手可以不太懂,可以看看,有经验的可以略去)
很多新手可能不理解这个句子,下面我们就一步一步的解释这个句子
查询满足条件的所有的数据安装id逆序排列
select * from terminal_online_statistic WHERE domain_moid = 'dcb80871-372b-4617-b329-9aafe6f78acb' && statistic_time BETWEEN '2015-08-04 10:57:48' AND '2015-08-04 14:57:49' order by id desc;
运行结果为:
然后我们去前几条的l原始imit语句
select * from terminal_online_statistic WHERE domain_moid = 'dcb80871-372b-4617-b329-9aafe6f78acb' && statistic_time BETWEEN '2015-08-04 10:57:48' AND '2015-08-04 14:57:49' order by id desc limit 0,3
效果如下:
优化的limit语句很多人可能刚开始写的如下.
select * from terminal_online_statistic where id<=(select id from terminal_online_statistic WHERE domain_moid = 'dcb80871-372b-4617-b329-9aafe6f78acb' && statistic_time BETWEEN '2015-08-04 10:57:48' AND '2015-08-04 14:57:49' order by id desc limit 0,1) order by id desc limit 3.
运行结果如下:
可以看到不满足条件的也运行出来了。
原因如下:我们子查询的语句做了筛选,满足其第一条的id为49,但是我们外面的查询没有做筛选,导致外面是查询所有的id<49的数据,然后逆序排列,然后之显示3条。
外层的也要做筛选,正确的语句如下:
select * from terminal_online_statistic where domain_moid = 'dcb80871-372b-4617-b329-9aafe6f78acb' && statistic_time BETWEEN '2015-08-04 10:57:48' AND '2015-08-04 14:57:49' && id<=(select id from terminal_online_statistic WHERE domain_moid = 'dcb80871-372b-4617-b329-9aafe6f78acb' && statistic_time BETWEEN '2015-08-04 10:57:48' AND '2015-08-04 14:57:49' order by id desc limit 0,1) order by id desc limit 3
正确的结果与原始的limit分页语句一模一样。