我有一个正在PGSQL上运行的查询,当快速查询大型数据集时,由于它没有利用可用的索引,因此运行时间很长。我发现将过滤器从多个OR更改为IN子句会导致使用正确的索引。有没有办法即使在使用OR时也可以强制使用索引?
与析取查询
SELECT field1, field2,..., fieldN
FROM table1 WHERE
((((field9='val1' OR field9='val2') OR field9='val3') OR field9='val4')
AND (field6='val5'));
查询计划:
"Bitmap Heap Scan on table1 (cost=18.85..19.88 rows=1 width=395) (actual time=0.017..0.017 rows=0 loops=1)"
" Recheck Cond: (((field6)::text = 'val5'::text) AND (((field9)::text = 'val1'::text) OR ((field9)::text = 'val2'::text) OR ((field9)::text = 'val3'::text) OR ((field9)::text = 'val4'::text)))"
" -> BitmapAnd (cost=18.85..18.85 rows=1 width=0) (actual time=0.016..0.016 rows=0 loops=1)"
" -> Bitmap Index Scan on idx_field6_field9 (cost=0.00..9.01 rows=611 width=0) (actual time=0.015..0.015 rows=0 loops=1)"
" Index Cond: ((field6)::text = 'val5'::text)"
" -> BitmapOr (cost=9.59..9.59 rows=516 width=0) (never executed)"
" -> Bitmap Index Scan on idx_id_field9 (cost=0.00..2.40 rows=129 width=0) (never executed)"
" Index Cond: ((field9)::text = 'val1'::text)"
" -> Bitmap Index Scan on idx_id_field9 (cost=0.00..2.40 rows=129 width=0) (never executed)"
" Index Cond: ((field9)::text = 'val2'::text)"
" -> Bitmap Index Scan on idx_id_field9 (cost=0.00..2.40 rows=129 width=0) (never executed)"
" Index Cond: ((field9)::text = 'val3'::text)"
" -> Bitmap Index Scan on idx_id_field9 (cost=0.00..2.40 rows=129 width=0) (never executed)"
" Index Cond: ((field9)::text = 'val4'::text)"
"Planning time: 0.177 ms"
"Execution time: 0.061 ms"
使用IN查询
SELECT field1, field2,..., fieldN
FROM table1
WHERE
((field9 IN ('val1', 'val2', 'val3', 'val4'))
AND (field6='val5'));
查询计划:
"Index Scan using idx_field6_field9 on table1 (cost=0.43..6.77 rows=1 width=395) (actual time=0.032..0.032 rows=0 loops=1)"
" Index Cond: (((field6)::text = 'val5'::text) AND ((field9)::text = ANY ('{val1,val2,val3,val4}'::text[])))"
"Planning time: 0.145 ms"
"Execution time: 0.055 ms"
在字段6和9上有一个索引,第二个查询按预期使用了索引,第一个查询也应如此。 Field9也类似于状态字段,因此其基数非常低-整个表中只有9个不同的值。不幸的是,更改查询以使用IN子句并非易事,因此让PG使用正确的计划将是理想的选择。
答案 0 :(得分:1)
使用OR
条件无法获得快速计划(单索引扫描)。您必须重写查询。
您想知道为什么,这总是很难解释。进行这样的优化通常有两个原因:
没人无所事事。
每次计划使用OR
的查询时,这都需要额外的精力:
是否有与OR
关联的多个条件在一侧具有相同的表达?
两个计划(原始计划和重写计划)都必须估算。很有可能BitmapOr是处理查询的最有效方法。
每个查询中包含OR
的查询都必须支付此价格。
我并不是说添加这样的优化不是一个好主意,但是硬币有两个方面。