最新消息:

MySQL 分页查询优化 LIMIT与COUNT优化

mysql admin 4687浏览 0评论

老方法

传统分页查询,一般通过COUNT()函数事先获知总记录数据$amount
select count(*) as amout from tbl_name where uid = 1
然后可以通过ceil($amount / $page_size) 最终可以求知一共有多少页,告之用户。
p_329_001

具体实现,我这里就不再赘述了。

新方法

随着越来越非富的UI表现方式,用户并不观注有多少页,比如,一些社区游戏的好友列表常常不关注总页数,只管上下翻页

p_329_002

基本这种表现,我们没有必要浪费一条COUNT(*)查询。新办法其实很简单,不去统计总页数,而告诉客户端是否到达了最后一页。要告诉客户端是否到达了最后一页,只需要每次多查询一行记录。

function page_friend($page = 1, $page_size = 8) {
    global $user;
    if ($page < 1) {
        $page = 1;
    }

    //$page_size + 1,多取一行记录
    $result = db_query(
       "SELECT * FROM friends WHERE uid = %d ORDER BY fuid LIMIT %d, %d",
       array($user->uid, ($page - 1) * $page_size, $page_size + 1)
    );

    $friends = array();
    while ($f = db_fecth_object($result)) {
        $friends[] = $f;
    }

    $page_is_last = true;
    if (count($friends) >= $page_size + 1) {
        $page_is_last = false;
        array_pop($friends);
    }

    return array(
       'page'    => $page,
       'page_size' => $page_size,
       'page_is_last' => $page_is_last,
       'items' => $friends
    );
}

缺点:不能够显示总页码数,不能随意翻到指定页,只能上下翻页。
优点:每次请求都省去了一条COUNT查询,节约了服务器资源。

能不能再快一点

  1. 当一个数据库表过于庞大,LIMIT offset, length中的offset值过大,则SQL查询语句会非常缓慢,你需增加order by,并且order by字段需要建立索引。
  2. 如果使用子查询去优化LIMIT的话,则子查询必须是连续的,某种意义来讲,子查询不应该有where条件,where会过滤数据,使数据失去连续性。
  3. 如果你查询的记录比较大,并且数据传输量比较大,比如包含了text类型的field,则可以通过建立子查询。
    SELECT id,title,content FROM items WHERE id IN (SELECT id FROM items ORDER BY id limit 900000, 10);
  4. 如果limit语句的offset较大,你可以通过传递pk键值来减小offset = 0,这个主键最好是int类型并且auto_increment
    SELECT * FROM users WHERE uid > 456891 ORDER BY uid LIMIT 0, 10;
    这条语句,大意如下:
    SELECT * FROM users WHERE uid >=  (SELECT uid FROM users ORDER BY uid limit 895682, 1) limit 0, 10;
  5. 如果limit的offset值过大,用户也会翻页疲劳,你可以设置一个offset最大的,超过了可以另行处理,一般连续翻页过大,用户体验很差,则应该提供更优的用户体验给用户。

转载请注明:爱开源 » MySQL 分页查询优化 LIMIT与COUNT优化

您必须 登录 才能发表评论!