在处理分页结果时,跟踪项目总数的理想方法是什么?
这一开始似乎是一个简单的问题,但是当我真正开始考虑如何有效地做到这一点时,对我来说......如果你发现这对于文字来说太愚蠢了,那就更加复杂了。
我需要从数据库中获取一些项目。这很简单。然后,我可以将此计数存储在某个变量中(例如$ _SESSION变量)。我可以查看是否设置了此变量,如果不是,请再次计算。技巧部分是决定什么是确定何时需要获得新计数的最佳方法。如果我在总数中添加/删除了项目,或者我正在重新加载或重新访问网格,我似乎需要获得一个新计数。
那么,我如何决定何时清除这个$ _SESSION变量?我可以看到清除它并在更新/删除之后得到一个新的计数(或者甚至添加或减去它以避免可能昂贵的数据库命中)但是(这里是我觉得棘手的部分)当有人导航离开页面时怎么办?或者在转到结果的下一页或重新加载页面之前等待一段可变的时间?
由于我们可能正在处理数十或数十万个结果,从数据库中计算它们可能相当昂贵(对吗?或者我的假设不正确?)。因为我需要总计数来处理分页结果中的总页数...处理这种情况并保持它的最有效方法是什么......只要可能需要它?
顺便说一句,我会通过SQL查询得到计数:SELECT COUNT(id) FROM foo;
答案 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)更差。 (问题:它更好吗?)
的有趣文章答案 2 :(得分:1)
很可能foo
在PRIMARY KEY
列上定义了id
索引。数据库上的索引COUNT()
查询通常非常简单。
但是,如果你想加倍努力,另一种选择是在代码中插入一个特殊的钩子来处理插入和删除行foo
。让它在每次插入/更新后将总记录数写入受保护文件并从那里读取。如果考虑到每个成功的插入/更新,受保护文件中的数字始终是最新的。