IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

Mysql中的分页写法

Incessant 2009-10-11 22:34:47 累计浏览 4,834 次
本机暂存
基本上分页都是通过两个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. 使用deepseek进行Oracle恢复,引起重大故障 (2026-06-22 10:56:00)
  2. 接手一个只差临门一脚的数据库恢复 (2026-06-18 00:13:09)
  3. 我做了一个 AI 版的 StarRocks 升级风险扫描工具,直接帮我定位到一个风险 (2026-06-15 01:00:00)

查看更多 数据库 文章 →

建议继续学习

  1. 用Hyer来进行网站的抓取 (累计阅读 158,251)
  2. MySQL数据库在实际应用一些方面的介绍 (累计阅读 36,399)
  3. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,164)
  4. Mysql监控指南 (累计阅读 21,351)
  5. 由浅入深探究mysql索引结构原理、性能分析与优化 (累计阅读 16,523)
  6. 如何查找消耗资源较大的SQL (累计阅读 15,211)
  7. 在Apache2.2.XX下安装Mod-myvhost模块 (累计阅读 13,057)
  8. 15个最好的免费开源电子商务平台 (累计阅读 12,541)
  9. 浅谈MySQL索引背后的数据结构及算法 (累计阅读 11,908)
  10. 整理了一份招PHP高级工程师的面试题 (累计阅读 11,708)