2011-01-05 54 views
1

在处理分页结果时,跟踪项目总数的理想方式是什么?跟踪一系列分页结果中的项目总数

起初这看起来像一个简单的问题,但当我真正开始考虑如何有效地做到这一点时,它稍微复杂一点(对我来说......现在只是保释,如果你觉得这太愚蠢了)。

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

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

由于我们可能正在处理数十或数十万个结果,因此从数据库中计算它们可能会非常昂贵(对吗?或者我的假设是错误的?)。因为我需要总数来处理分页结果中的页面总数......处理这种情况的最有效方式是什么,并且只要可能需要,就可以坚持这种方式?

BTW,我会得到的计数与一个SQL查询,如:

SELECT COUNT(id) FROM foo; 
+1

在这么多的结果,你可能只是想使用一个四舍五入的数字,并说约22K的结果或类似的东西。 – dqhendricks 2011-01-05 22:18:23

回答

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中试过。

+0

@Scuzzy我认为,返回* LIMIT'子句后面的行数*之前。 – jeroen 2011-01-05 22:55:48

+0

啊,我的错误,我的评论是错误的,我已经删除它。 – Scuzzy 2011-01-05 23:13:07

1

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

这样做的一个好方法是使用一个ORM来为你做,比如Doctrine,它有一个result cache

为了获得计数,我知道使用COUNT(*)并不比使用COUNT(id)更差。 (问题:是不是更好呢?)

编辑:关于这个有趣的文章the MySQL performance blog

+0

“为什么将它存储在会话变量中?”唯一的原因是它可以在他们在结果页面之间移动的时间内重复使用。假设APC,memcached和/或Doctrine不可用,您是否还有其他建议?这些建议很有用......只是寻找最完美的骨骼来完成这个任务。 – Lothar 2011-01-05 22:30:24

+0

问题是,使用缓存系统时,缓存将跨越页面和用户,这是一个巨大的好处。如果我推荐的这两种酷工具都不可用,那么您仍然可以构建自己的缓存系统,如下所示:http://www.siteduzero.com/tutoriel-3-31906-comprendre-et-utiliser-un- systeme-de-cache-php.html但是,安装和使用这些工具要简单得多 – greg0ire 2011-01-05 22:33:59

+1

格雷格正在讨论基于文件的缓存,这些缓存不是用户特定的,例如:http://www.jongales.com/blog/2009/ 02/18/simple-file-based-php-cache-class /你将创建一个有效期过期的文件,它将检查每次页面加载时是否出现数据,然后删除它,然后重新运行查询 – RobertPitt 2011-01-05 22:40:34

1

最有可能fooid列定义的PRIMARY KEY指数。索引COUNT()查询通常在数据库上很容易。

但是,如果您想要多走一步,另一个选择是在代码中插入一个特殊的钩子,以处理插入和删除行到foo。让它在每次插入/更新后将总记录数写入受保护的文件并从那里读取。如果每个成功的插入/更新得到说明,受保护文件中的编号始终是最新的。