я встретил странное поведение оптимизатора 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
является булевым, имеющим индекс ВТКЕЯ и 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 может обрабатывать нулевые проверки, поэтому я не понимаю, почему индекс не используется для полного запроса. В таблице продуктов содержится около 2,3 миллиона записей, поэтому это не очень быстро.
EDIT: Индекс стандартны:
CREATE INDEX idx_prod_aggr
ON product
USING btree
(aggregatorid COLLATE pg_catalog."default");
Можете ли вы показать нам результат «объяснить анализ»? –
@a_horse_with_no_name Я добавил оба объяснения результатов анализа. –
Возможно ли, что слишком много строк с нулями в aggregatorId? –