我一直认为大型WHERE x IN
子句的查询效果不佳。
例如,假设我有下表
psql> \d examples
| Column | Type | Modifiers
| id | integer | not null default nextval('id_seq'::regclass)
| flag | boolean | not null
| date | timestamp | not null
| comment | character varying(16) | not null
Indexes:
"example_pkey" PRIMARY KEY, btree (id)
如果我使用带有100k ID的WHERE id IN
子句查询此表,它实际上很快返回(表中有100ks行):
EXPLAIN ANALYSE SELECT * FROM examples WHERE id IN (1, 2, ...., 100000);
Index Scan using examples_pkey on examples (cost=0.15..15012.60 rows=610 width=104) (actual time=18.380..18.380 rows=0 loops=1)
Index Cond: (id = ANY ('{1, 2, ... 100000}'::integer[]))
Planning time: 45.832 ms
Execution time: 42.708 ms
规划人员已经重写了查询,以便将id = ANY
与我的ID列表一起使用,所以我认为这只是等价的,或者规划者知道这更快。
在使用子查询替换大WHERE IN
子句之前,我已经有了其他查询,这极大地提高了查询的速度。我的查询非常简单,所以问题是:
具有大WHERE IN
个子句的查询是否真的表现不佳?如果是这样的情况(假设列是索引等)。
答案 0 :(得分:0)
解析器将列表中包含多个元素的IN
表达式转换为=ANY
表达式。
如果列上有B树索引,则可以始终使用它。
我能想到的唯一性能问题是优化器可能会错误地估计结果行的数量,并在索引扫描实际上更快时选择顺序扫描。
实验表明,优化程序为唯一列估计每个列表条目的一个结果行,并且最多包含表中的行数。这是一个合理的估计,但如果列表中有许多元素不匹配或存在重复,则估计值可能很高。