mysql> select count(1) from sys_log;
+----------+
| count(1) |
+----------+
| 22589 |
+----------+
mysql> select * from sys_log order by create_date desc limit 20000,10 ;
//省却....
10 rows in set (2.79 sec)
limit 20000,10,此时MySql会筛选出前20010条记录,而仅仅返回 20000-20010之间的10条记录。前20000条记录会被抛弃,查询效率很低。
一、利用索引
SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) LIMIT M
适用于数据量多的情况(元组数上万)
索引扫描,速度会很快. 有朋友提出: 因为数据查询出来并不是按照pk_id排序的,所以会有漏掉数据的情况,只能方法二。
二、基于索引再排序
SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) ORDER BY id_pk ASC LIMIT M
适用于数据量多的情况(元组数上万). 最好ORDER BY后的列对象是主键或唯一所以,使得ORDERBY操作能利用索引被消除但结果集是稳定的。
三、使用子查询
这种方式先定位偏移位置的 id,然后往后查询,这种方式适用于 id 递增的情况。
select * from orders_history where type=8 limit 100000,1;
select id from orders_history where type=8 limit 100000,1;
select * from orders_history where type=8 and id>=(select id from orders_history where type=8 limit 100000,1) limit 100;
select * from orders_history where type=8 limit 100000,100;
4条语句的查询时间如下:
第1条语句:3674ms
第2条语句:1315ms
第3条语句:1327ms
第4条语句:3710ms
四、使用连接查询
如果表ID非数字递增的情况
mysql> select a.* from sys_log a INNER JOIN (select id from sys_log order by create_date desc limit 20000,10 ) b on a.id=b.id;
//省却....
10 rows in set (0.12 sec)