分页数据,必须是更好的方法

时间:2010-06-17 16:14:34

标签: php postgresql pagination

我读过10个左右的“教程”,它们都涉及同样的事情:

  • 拉取数据集的计数
  • 拉出相关数据集(LIMIT,OFFSET)

IE:

SELECT COUNT(*) 
  FROM table 
 WHERE something = ?

SELECT * 
  FROM table 
 WHERE something =? 
 LIMIT ? offset ?`

两个非常相似的查询,不是吗?必须有一个更好的方法来做到这一点,我的数据集是600,000多行并且已经迟缓(结果由超过30个where子句确定,并且因用户而异,但当然正确索引)。

4 个答案:

答案 0 :(得分:2)

不幸的是,为了获得查询时的确切计数,postgresql必须遍历符合条件的所有行,并查看它们是否对您的事务可见。但是您可能不需要完全计数,因为只要您将结果发送给用户,结果就会过时。所以你可以尝试一些事情:

  1. 缓存后续查询的计数,因此成本仅适用于第一页(可能没什么用,大多数人只看第一页)
  2. 如果查询映射良好,请使用专门的反向索引搜索引擎进行搜索。 Lucene / Solr是个不错的选择。
  3. 如果有时疯狂关闭计数不是问题,请使用postgresql的内置统计信息来估计可能匹配的行数。您可以通过对查询执行EXPLAIN来获取数字。增加至少相关表的统计目标,以获得更准确的数字。由于计划程序不知道不同谓词之间的相关性并假设它们不相关,因此使用多个谓词时数字可能仍然明显偏离。因此WHERE sex='male' AND has_breasts=true之类的东西会假设25%会匹配,这可能是一个数量级的关闭。如果您使用analyze运行说明,则可以检查计划程序预计必须经历多少行才能获得结果的第一页,实际需要经历多少行,并相应地缩放估计值。这可能与Google用于估算与您的查询匹配的页数有些类似。如果我没记错的话,Lucene应该支持类似的估计。

答案 1 :(得分:1)

使用统计数据进行计数估算。这将有助于创建,并且不会给你带来太多开销。

请参阅http://wiki.postgresql.org/wiki/Count_estimate

答案 2 :(得分:0)

您可能需要考虑使用光标。

答案 3 :(得分:0)

您可以CREATE TABLE AS并将所有结果放在新表中。如果TEMP表不是一个选项,则必须管理创建的表。