您的位置:首页 > 数据库 > MySQL

Mysql分页查询高效方案

2016-11-01 10:24 197 查看
很久以前的一次面试中,被面试官问到这个问题,由于平时用到的分页方法不多,只从索引、分表、使用子查询精准定位偏移以外,没有使用到其它方法。

后来在看其它博客看到了一些不同的方案,也一直没有整理。今天有时间,整理出来,分享给大家。

一,最常见MYSQL最基本的分页方式:

select * from content order by id desc limit 0, 10


在中小数据量的情况下,这样的SQL足够用了,唯一需要注意的问题就是确保使用了索引。随着数据量的增加,页数会越来越多,查看后几页的SQL就可能类似:

select * from content order by id desc limit 1000000, 10


一言以蔽之,就是越往后分页,LIMIT语句的偏移量就会越大,速度也会明显变慢。

此时,我们可以通过2种方式:

一,子查询的分页方式来提高分页效率,SQL语句如下:

SELECT * FROM table WHERE id >= (SELECT id FROM table LIMIT 1000000, 1) LIMIT 10;


为什么会这样呢?因为子查询是在索引上完成的,而普通的查询时在数据文件上完成的,通常来说,索引文件要比数据文件小得多,所以操作起来也会更有效率。通过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倍!

可是,还不是完美的!

SELECT * FROM table WHERE id BETWEEN 1000000 AND 1000010;


用这句速度会更快。

另外,如果需要查询 id 不是连续的一段,最佳的方法就是先找出 id ,然后用 in 查询:

SELECT * FROM table WHERE id IN(10000, 100000, 1000000...);


二,使用MYSQL的FOUND_ROWS()函数

Mysql FOUND_ROWS() 函数结合SQL_CALC_FOUND_ROWS在SELECT中可以得到两个结果:

1. 得到Limit的内容

2. 得到去除Limit以后所有行数

SELECT语句中经常可能用LIMIT限制返回行数。有时候可能想要知道如果没有LIMIT会返回多少行,但又不想再执行一次相同语句。那么,在SELECT查询中包含SQL_CALC_FOUND_ROWS选项,然后执行FOUND_ROWS()就可以了:

select SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT FOUND_ROWS();


其中SQL_CALC_FOUND_ROWS 告诉Mysql将sql所处理的行数记录下来,FOUND_ROWS() 则取到了这个纪录。 虽然也是两个语句,但是只执行了一次主查询,所以效率比原来要高很多。

如果在前一条语句中使用SQL_CALC_FOUND_ROWS选项,FOUND_ROWS()将返回第一条语句没有LIMIT时返回的行数。

如果在前一条语句中没有使用SQL_CALC_FOUND_ROWS选项,FOUND_ROWS()将返回前一条语句实际返回的行数。

如果使用 SELECT SQL_CALC_FOUND_ROWS,MySQL必须计算所有结果集的行数。尽管这样,总比再执行一次不使用LIMIT的查询要快多了吧,因为那样结果集要返回客户端滴。(另外:应该不单是没有将结果集返回的原因,还有原因可能是比如LIKE之类比较费劲的SQL不需要再去劳累一次。)

– 注意下面语句中的条件 LIKE

SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE Name LIKE ‘%string%’ id > 100 LIMIT 10;

SELECT FOUND_ROWS();

– 上面语句等价于下面语句,但性能方面应该提升非常非常的明显:

SELECT COUNT(*) FROM tbl_name WHERE Name LIKE ‘%string%’ ;

SELECT * FROM tbl_name WHERE Name LIKE ‘%string%’ id > 100 LIMIT 10;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql 分页