postgresql COUNT(DISTINCT …)很慢

我有一个非常简单的SQL查询:

SELECT COUNT(DISTINCT x) FROM table; 

我的桌子有大约150万行。 这个查询运行的很慢, 大约需要7.5s,相比之下

  SELECT COUNT(x) FROM table; 

大约需要435ms。 有没有办法改变我的查询来提高性能? 我已经尝试了分组,并进行了常规计数,并将索引放在x上; 两者具有相同的7.5s执行时间。

你可以使用这个:

 SELECT COUNT(*) FROM (SELECT DISTINCT column_name FROM table_name) AS temp; 

这比以下要快得多:

 COUNT(DISTINCT column_name) 
 -- My default settings (this is basically a single-session machine, so work_mem is pretty high) SET effective_cache_size='2048MB'; SET work_mem='16MB'; \echo original EXPLAIN ANALYZE SELECT COUNT (distinct val) as aantal FROM one ; \echo group by+count(*) EXPLAIN ANALYZE SELECT distinct val -- , COUNT(*) FROM one GROUP BY val; \echo with CTE EXPLAIN ANALYZE WITH agg AS ( SELECT distinct val FROM one GROUP BY val ) SELECT COUNT (*) as aantal FROM agg ; 

结果:

 original QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Aggregate (cost=36448.06..36448.07 rows=1 width=4) (actual time=1766.472..1766.472 rows=1 loops=1) -> Seq Scan on one (cost=0.00..32698.45 rows=1499845 width=4) (actual time=31.371..185.914 rows=1499845 loops=1) Total runtime: 1766.642 ms (3 rows) group by+count(*) QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- HashAggregate (cost=36464.31..36477.31 rows=1300 width=4) (actual time=412.470..412.598 rows=1300 loops=1) -> HashAggregate (cost=36448.06..36461.06 rows=1300 width=4) (actual time=412.066..412.203 rows=1300 loops=1) -> Seq Scan on one (cost=0.00..32698.45 rows=1499845 width=4) (actual time=26.134..166.846 rows=1499845 loops=1) Total runtime: 412.686 ms (4 rows) with CTE QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------ Aggregate (cost=36506.56..36506.57 rows=1 width=0) (actual time=408.239..408.239 rows=1 loops=1) CTE agg -> HashAggregate (cost=36464.31..36477.31 rows=1300 width=4) (actual time=407.704..407.847 rows=1300 loops=1) -> HashAggregate (cost=36448.06..36461.06 rows=1300 width=4) (actual time=407.320..407.467 rows=1300 loops=1) -> Seq Scan on one (cost=0.00..32698.45 rows=1499845 width=4) (actual time=24.321..165.256 rows=1499845 loops=1) -> CTE Scan on agg (cost=0.00..26.00 rows=1300 width=0) (actual time=407.707..408.154 rows=1300 loops=1) Total runtime: 408.300 ms (7 rows) 

与CTE相同的计划也可能由其他方法(窗函数)产生,

如果您的count(distinct(x))明显慢于count(x)那么您可以通过在不同的表中维护x值计数table_name_x_counts (x integer not null, x_count int not null)例如, table_name_x_counts (x integer not null, x_count int not null) ,使用触发器。 但是你的写性能会受到影响,如果你在单个事务中更新了多个x值,那么你需要按照一定的顺序来做这件事,以避免可能的死锁。