sql - 在greenplum / postgreSQL中count(*)和count(*)over()性能差异
问题描述
我想查询明细数据和明细数据的总数。一般来说,这需要两句SQL。例如,一个是select col1, col2, col3 from tb limit 50 offset 0
,另一个是select count() from tb
。为了减少查询次数,我改用“select col1, col2, col3, count() over () totol_count from tb”。
但我发现后者(select col1, col2, col3, count(*) over () totol_count from tb limit 50 offset 0
)有时比前者慢得多。为什么?两种方法的性能差异是什么?
这是解释分析。我只是把不同的地方放在上面。
select col1 from tb limit 20 offset 0 Limit (cost=743828.93..747114.71 rows=200 width=287) (actual time=2290.254..2390.969 rows=200 loops=1) -> Gather Motion 20:1 (slice3; segments: 20)(成本=743828.93..747114.71 行=200 宽度=287)(实际时间=2290.248..2390.933 行=200 循环=1)-> 限制(成本=743828.93..747110.71 行=10 宽度=287)(实际时间=2285.350..2385.507 行=200 循环=1)
select count(*) from tb Aggregate (cost=6123212.33..6123212.34 rows=1 width=8) (实际时间=2339.615..2339.616 rows=1 loops=1) -> Gather Motion 20:1 (slice2; segments: 20 )(成本=6123212.10..6123212.32 行=1 宽度=8)(实际时间=635.672..2339.433 行=20 循环=1)-> 聚合(成本=6123212.10..6123212.11 行=1 宽度=8)(实际时间=633.879..633.879 行=1 循环=1)
select col, count(*) over() from tb limit 20 offset 0 Limit (cost=743828.93..747113.21 rows=200 width=287) (实际时间=57787.942..57788.339 rows=200 loops=1) -> WindowAgg ( cost=743828.93..307341631.82 rows=18670608 width=287) (实际时间=57787.936..57788.310 rows=200 loops=1) -> Gather Motion 20:1 (slice3; segments: 20) (cost=743828.93..307014896.18 rows =18670608 宽度=287) (实际时间=1514.368..32796.802 行=18735134 循环=1)
解决方案
只有在看到您的执行计划后,才能确定哪个是您更好的选择。
但是,如果您运行足够的分析,您可以使用:
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'tb'::regclass;
它非常快,但不会给你准确的计数,而是一个近似值。准确性取决于运行分析的频率。
之所以
select count(*) from tb
慢,与 PostgreSQL 中的 MVCC 实现有关。多个事务可以看到数据的不同状态这一事实意味着“COUNT(*)”没有直接的方法来汇总整个表中的数据;从某种意义上说,PostgreSQL 必须遍历所有行。这通常会导致顺序扫描读取有关表中每一行的信息。 PostgreSQL 中的慢计数
推荐阅读
- c# - 当我刷新数据网格时,“选定的值”直到第二次单击才会改变
- wso2esb - 创建 WSO2 EI 数据源时如何解决错误
- python - 如何在 python 中清理包含 \n 和不必要的空格且格式错误的 JSON 数据?
- php - 有没有办法阻止某人执行他必须下载的 php
- django - 如何在 Django 中的父字段上进行内部连接
- python - 有条件地创建新行
- sql - 旋转重复项的最佳方法是什么?
- java - 使用 Spring Boot 的 OAuth2 中的 FileNotFoundException
- database - 无法在 MariaDB 中为 wordpress 设置数据库
- html - 用于计算的无线电代码和数字输入以及您要求的文件的错误不存在