【发布时间】:2015-06-11 09:12:37
【问题描述】:
我在以下查询中遇到了 Postgres 优化器的奇怪行为:
select count(product0_.id) as col_0_0_ from Product product0_
where product0_.active=true
and (product0_.aggregatorId is null
or product0_.aggregatorId in ($1 , $2 , $3))
Product 大约有 54 列,active 是具有 btree 索引的布尔值,aggregatorId 是 'varchar(15)` 并具有 btree 索引。
在上面的查询中,没有使用“aggregatorId”的索引:
Aggregate (cost=169995.75..169995.76 rows=1 width=32) (actual time=3904.726..3904.727 rows=1 loops=1)
-> Seq Scan on product product0_ (cost=0.00..165510.39 rows=1794146 width=32) (actual time=0.055..2407.195 rows=1851827 loops=1)
Filter: (active AND ((aggregatorid IS NULL) OR ((aggregatorid)::text = ANY ('{5109037,5001015,70601}'::text[]))))
Rows Removed by Filter: 542146
Total runtime: 3904.925 ms
但是如果我们通过省略对该列的空检查来减少查询,则索引会被使用:
Aggregate (cost=17600.93..17600.94 rows=1 width=32) (actual time=614.933..614.935 rows=1 loops=1)
-> Index Scan using idx_prod_aggr on product product0_ (cost=0.43..17487.56 rows=45347 width=32) (actual time=19.284..594.509 rows=12099 loops=1)
Index Cond: ((aggregatorid)::text = ANY ('{5109037,5001015,70601}'::text[]))
Filter: active
Rows Removed by Filter: 49130
Total runtime: 150.255 ms
据我所知,btree 索引可以处理空检查,所以我不明白为什么索引不用于完整查询。产品表包含大约 230 万个条目,因此速度不是很快。
编辑: 指标很标准:
CREATE INDEX idx_prod_aggr
ON product
USING btree
(aggregatorid COLLATE pg_catalog."default");
【问题讨论】:
-
你能告诉我们
explain analyze的输出吗? -
@a_horse_with_no_name 我已经添加了解释分析结果。
-
aggregatorId 中的空行是否可能太多?
-
@DraganBozanovic 太多是什么意思?空值占多数(约 1.8m)。
-
请看下面我的回答。
标签: sql postgresql