技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> Mysql中的分页写法

Mysql中的分页写法

浏览:3928次  出处信息
基本上分页都是通过两个sql来实现的,一个查询count(*),一个查询list,如下:

    mysql> select count(*) from test;

    +----------+

    | count(*) |

    +----------+

    | 2097152 |

    +----------+

    1 row in set (0.00 sec)

mysql> select * from test limit 10;

    +--------+------+

    | a | b |

    +--------+------+

    | 62599 | |

    | 158694 | |

    | 155279 | |

    | 233810 | |

    | 160137 | |

    | 221035 | |

    | 174371 | |

    | 242246 | |

    | 147503 | |

    | 257907 | |

    +--------+------+

    10 rows in set (0.00 sec)

    Mysql中引出了另外的分页实现方式,通过sql_calc_found_rows,found_rows()查询一次就可以实现,减少了数据库的调用次数。

    1.计算全部结果集合中有多少,这比不用LIMIT而再次运行问询要快,原因是结果集合不需要被送至客户端。

    mysql> select sql_calc_found_rows * from test limit 10;

    +--------+------+

    | a | b |

    +--------+------+

    | 62599 | |

    | 158694 | |

    | 155279 | |

    | 233810 | |

    | 160137 | |

    | 221035 | |

    | 174371 | |

    | 242246 | |

    | 147503 | |

    | 257907 | |

    +--------+------+

    10 rows in set (3.45 sec)

    2.直接取出count(*)总数

    mysql> select found_rows();

    +--------------+

    | found_rows() |

    +--------------+

    | 2097152 |

    +--------------+

    1 row in set (0.00 sec)

    sql_calc_found_rows 和 found_rows() 在当你希望限制返回的行数时很有用,你不需要再次根据count(*)取到结果集。最明显的例子就是Web 分页list分页脚本,使用found_rows() 你可以很容易确定剩下的结果需要多少其它的页。

    通过 found_rows()的有效行数是瞬时的,并且不用于越过SELECT sql_calc_found_rows语句后面的语句,你要是需要保留这个值。

    mysql> select sql_calc_found_rows * from ... ;

    mysql> set @rows = found_rows();

Mysql中翻页如何实现?

    通常分页比如论坛帖子,我们一般都会看好几页,比如这个帖子非常火,分页翻到了第100页,这种语句的实现方式:

    mysql> select * from test where a>10 limit 1000,10 ;

    +--------+------+

    | a | b |

    +--------+------+

    | 187673 | |

    | 187721 | |

    | 187760 | |

    | 187780 | |

    | 187816 | |

    | 187821 | |

    | 187827 | |

    | 187891 | |

    | 187893 | |

    | 187966 | |

    +--------+------+

    10 rows in set (0.01 sec)

    这么写的话通常需要扫描表的前1010行,大家都知道回表的代价是很大的,而随着翻页的增加,扫描的代价会越来越大,我们是否可以采取另外的实现方式。

    1.先根据索引去取出a,这个地方只能走索引

    mysql> select a from test where a>10 limit 1000,10 ;

    +--------+

    | a |

    +--------+

    | 187673 |

    | 187721 |

    | 187760 |

    | 187780 |

    | 187816 |

    | 187821 |

    | 187827 |

    | 187891 |

    | 187893 |

    | 187966 |

    +--------+

    10 rows in set (0.00 sec)

    2.根据取到的记录id再去回表

    mysql> select t1.* from test t1,(select a from test where a>10 limit 1000,10) t2 where t1.a=t2.a;

    这种实现方式只需要回表很少记录,因为取id是通过扫描来实现的,然后根据符合条件的记录数id来回表。

注:mysql中是不允许子查询中使用limit

    mysql> select * from test where a in(select a from test where a>10 limit 1000,10);

    ERROR 1235 (42000): This version of MySQL doesn\'t yet support \'LIMIT & IN/ALL/ANY/SOME subquery\'

建议继续学习:

  1. MYSQL分页limit速度太慢优化方法    (阅读:4383)
  2. 深入理解Linux内存管理机制(一)    (阅读:3876)
  3. 独创比百度、Google分页还强的分页类    (阅读:3709)
  4. 合理使用MySQL的Limit进行分页    (阅读:3027)
  5. 高效的MySQL分页    (阅读:2767)
  6. 用Twitter的cursor方式进行Web数据分页    (阅读:2282)
  7. 交互模式之分页还是加载?    (阅读:2023)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1