跟踪一系列分页结果中的项目总数

时间:2011-01-05 22:14:05

标签: php mysql pagination

在处理分页结果时,跟踪项目总数的理想方法是什么?

这一开始似乎是一个简单的问题,但是当我真正开始考虑如何有效地做到这一点时,对我来说......如果你发现这对于文字来说太愚蠢了,那就更加复杂了。

我需要从数据库中获取一些项目。这很简单。然后,我可以将此计数存储在某个变量中(例如$ _SESSION变量)。我可以查看是否设置了此变量,如果不是,请再次计算。技巧部分是决定什么是确定何时需要获得新计数的最佳方法。如果我在总数中添加/删除了项目,或者我正在重新加载或重新访问网格,我似乎需要获得一个新计数。

那么,我如何决定何时清除这个$ _SESSION变量?我可以看到清除它并在更新/删除之后得到一个新的计数(或者甚至添加或减去它以避免可能昂贵的数据库命中)但是(这里是我觉得棘手的部分)当有人导航离开页面时怎么办?或者在转到结果的下一页或重新加载页面之前等待一段可变的时间?

由于我们可能正在处理数十或数十万个结果,从数据库中计算它们可能相当昂贵(对吗?或者我的假设不正确?)。因为我需要总计数来处理分页结果中的总页数...处理这种情况并保持它的最有效方法是什么......只要可能需要它?

顺便说一句,我会通过SQL查询得到计数:

SELECT COUNT(id) FROM foo;

3 个答案:

答案 0 :(得分:3)

我从不使用会话变量来存储查询中找到的总数,我在获取信息时包含常规查询中的计数,而计数本身来自第二个查询:

// first query
SELECT SQL_CALC_FOUND_ROWS * FROM table LIMIT 0, 20;
// I don´t actually use * but just select the columns I need...

// second query
SELECT FOUND_ROWS();

我从未注意到由于第二个查询导致任何性能下降,但我想如果你想确定的话,你必须测量它。

顺便说一句,我在PDO中使用它,我没有在普通的MySQL中尝试过它。

答案 1 :(得分:1)

为什么要将它存储在会话变量中?每个用户的结果会改变吗?我宁愿将其存储在APC或memcached等用户缓存中,明智地选择缓存密钥,然后在插入或删除与查询相关的记录时将其清除。

执行此操作的一个好方法是使用为您执行此操作的ORM,例如具有result cache的Doctrine。

要获得计数,我知道使用COUNT(*)并不比使用COUNT(id)更差。 (问题:它更好吗?)

编辑:关于the MySQL performance blog

的有趣文章

答案 2 :(得分:1)

很可能fooPRIMARY KEY列上定义了id索引。数据库上的索引COUNT()查询通常非常简单。

但是,如果你想加倍努力,另一种选择是在代码中插入一个特殊的钩子来处理插入和删除行foo。让它在每次插入/更新后将总记录数写入受保护文件并从那里读取。如果考虑到每个成功的插入/更新,受保护文件中的数字始终是最新的。