关于mysql大数据量分页方法


关于mysql大数据量分页方法

一个mysql大数据分页方法,权当笔记,方便以后随时捡起。

刚来公司时,看到一个同事提到一种mysql大数据量分页方式,当时没感觉到价值所在,直到我也遇到同样的问题

mysql中 平时我们分页都是用limit num1,num2 ,这样的格式分页,不过有个问题,就是如果数据量非常大,页数很多,随着limit第一个参数num1偏移量的加大,mysql的查询速度也就变慢

举个栗子 有上百w或千w条数据,我们查询select * from tab1 limit 0,20 和select * from tab1 limit 1111111,20 虽然都是查出20条数据,但查询速度有很大区别,问题就出现在limit的第一个参数上

所以要想查询速度变快,我们需要将limit第一个参数尽量变小

下面简单分解下,借鉴的是同事的思路
比如我有100条数据的用户表user,有uid,uname,pwd 三个字段,其中id是自增主键,连续不连续无所谓,使用快速查询方式的步骤:
$perPage = 10; //假如我要分每页数据条数为10

$dataCount = (select count(*) from user); //查询总数据条数 –当然都是伪代码,重点说明思路

$pageCount = ceil($dataCount/$perPage); //获取总页数

我们正常分页是

获取用户请求的页数page,然后根据page和定义好的perPage来计算offset,从而limit offset,perPage

新的方法是

首先判断如果page等于第一页1,正序正常查询select * from user order by uid asc limit 0,10

然后判断如果page等于最后一页pageCount,

我们首先取余 $mod = $dataCount % $perpage; //查出最后一页数据条数

然后这样查询: select * from user order by uid desc limit 0,$mod; //取出最后一页数据 当然这里查出的数据需要排下序输出到页面

前面两个是预备动作,因为用户点击第一页和最后一页动作很平凡

然后开始说我们的那种比较好的查询方法

正常情况下页面会给我们传page,有时也有perPage,这次我们要加上三个参数currentPage,big,small //当前页,当前页最大主键id,当前页最小主键id

currentPage就是当前页,page是我们想要跳转到的页,然后每次查询出这个页面的数据后,比如我查出10条数据,big是10条数据里的uid最大值,small是最小值

我通常是每次查出数据后用foreach取出这一页id列表,用max,min取最大最小值

foreach($data as v){
 $uids[] = $v['uid'];
 }
 取出主键uid列表后求最大最小值
 $big = max($uids);
 $small = min($uids);


我们接收到page,currentPage,big,small后

判断page和currentPage的关系


if page>currentPage



  select* fromuserwhereuid > big orderbyuid asclimit (page - currentPage - 1)*perpage,perpage;



if page<currentPage



select* fromuserwhereuid < small orderbyuid desclimit (currentPage - page - 1)*perpage,perpage;



也可以用(abs(page-currentPage)-1) * perpage来计算offset

这样的话如果用户访问的两个page差不是很大,offset会非常小,所以查询速度会很快,当然,需要注意下查询出来的数据内容排序问题,拿这里面的例子说,就是第2条sql查出的数据需要倒序下输出到页面。

select * from table where id > 100000 limit 0,10