If PostgreSQL count(*) is always slow how to paginate complex queries?
如果PostgreSQL的count(*)总是很慢,如何分页复杂查询?
只要在这种情况下我们有很多页面(例如,不同的类别,过滤器等),制作触发器似乎不是一个好的解决方案。
如果VACUUM/VACUUM ANALYZE/ANALYZE/VACUUM FULL没有帮助怎么办? 在Postgresql中使用count(*)的最佳实践是什么?
-
无论使用哪种DBMS,任何条件下的计数(以及任何其他聚合函数)都完全取决于有用的索引。
-
count(*)与分页有何关系? 您能告诉我们您正在使用的声明吗? 在运行实际查询之前,是否还要运行额外的count(*)? 您是否尝试与主查询一起执行count(*)?
-
@a_horse_with_no_name count(*)用于计算页面数量。 我的语句是简单的SELECT count(*) from my_table(运行非常慢)和select count(pub_date) from catalog_ad where"catalog_ad"."pub_date">= 2013-04-20 00:00:00;(运行更快,但仍然很慢)。 我与主查询分开运行count。 我如何一起运行它们?
-
请参见此处:sqlfiddle.com/#!12/92045/1您可能还需要阅读以下内容:use-the-index-luke.com/sql/partial-results,以获取有关如何加快分页速度的更深入的信息。
-
检查我最近的答案,了解如何对条件和单一计数进行分页。
您是否阅读了该文章的标题?
Note that the following article only applies to versions of PostgreSQL prior to 9.2. Index-only scans are now implemented.
使用9.2,通常会发现您获得了更好的结果。 阅读仅索引扫描Wiki页面以获取详细信息。
也就是说,在较旧的版本上使用LIMIT和OFFSET通常可以正常工作。 如果您不介意任何变化,则可以使用表统计信息来估算行数(因此也可以估算页数)。 请参阅您已链接的文章中的"估计行数"。
无论如何,使用LIMIT和OFFSET进行分页都是一种反模式。 很多时候,您可以重新定义分页代码,以便它使用sort_column > 'last_seen_value' LIMIT 100,即避免偏移。 有时可能会导致很大的性能提升。
-
@Daniil您已经链接到答案了;只需阅读wiki.postgresql.org/wiki/Slow_Counting,"估计行数"
-
当我要计算整个表中的行时,多数民众赞成在很好的解决方案,但是如果我要过滤表怎么办?
-
@Daniil Count通常将能够使用带有过滤器的查询索引。直到9.2,它仍然必须进行堆查找,但是除非您执行与大多数表匹配的过滤器,否则应执行OK。否则:升级。
-
@Daniil记住阅读升级手册;请记住,它不是就地升级,您需要使用pg_upgrade或转储并重新加载。
-
刚刚升级到9.2。没有改变
-
@Daniil explain (buffers, analyze)然后;让我们看看它在做什么。
-
我也有同样的问题。即我需要对过滤结果进行分页。过滤器有多种用户定义的设置,即具有"超过9000个"变体。因此,缓存计数不是(可行的)选项。我把查询及其解释放在这里:gist.github.com/NoICE/59a915e4b2b522e574e8任何提示/帮助将不胜感激! :-) P.S.我不知道为什么添加联接(如要点所示)为什么会导致如此糟糕的性能下降(因为它被索引了,所以不应该...)。
-
虽然Query PLAN估算有效,但我可以在JPA下运行它。 JPA不允许我从触发功能获得结果。
-
根据" count(*)"现在快得多吗?这可能是原因:"仅索引扫描*可以*满足这些查询[...]。但是,在实践中这种可能性特别小。[...]"没有任何谓词的count(*)"查询如果索引比其表小得多,将仅使用仅索引扫描。通常仅在表的行宽比某些索引宽得多时才会发生。"
-
@CraigRinger这是您为我的示例数据请求的explain (buffers, analyze):gist.github.com/nh2/bbbff93be04ea6c5181ec948981081b1-您知道为什么链接的仅索引扫描Wiki页面中的Index Only Scan using categories_pkey on categories等同于此处?我们可以强迫它踢吗?
-
就我而言,VACUUM ANALYZE mytable;有所帮助:在它之后,我在explain中看到了Index Only Scan(请参见我的要点),并且提速了2倍。
-
...并且冷缓冲区缓存的速度提高了20倍。还想离开这里,只是ANALYZE没做,VACUUM ANALYZE做了。
如果您正在执行SELECT count(*)FROM table并启用了pg stats,则可以使用下面的示例,在这种情况下,示例从13ms降低到0.05ms。
1
| SELECT COUNT(*) FROM news; |
26171
1
| EXPLAIN ANALYZE SELECT COUNT(*) FROM news; |
总运行时间:13.057毫秒
1
| SELECT reltuples::BIGINT AS COUNT FROM pg_class WHERE oid = 'public.news'::regclass; |
26171
1
| EXPLAIN ANALYZE SELECT reltuples::BIGINT AS COUNT FROM pg_class WHERE oid = 'public.news'::regclass; |
总运行时间:0.053毫秒
-
要确认性能差异:(0.4ms) SELECT reltuples::bigint AS count FROM pg_class WHERE oid = public.aggregate_data_points::regclass与(398.9ms) SELECT COUNT(*) FROM"aggregate_data_points"
-
这两个查询给出不同的结果。
-
考虑到第二个查询(带有reltuples)仅是一个估计值,它不会总是产生准确的值。
-
@JhulianoMoreno估计有多接近?以及这个估计会产生什么影响
-
您如何向其中添加过滤器(如where子句)?