什么时候查询非常大的“WHERE x IN”子句表现不好?

时间:2018-01-17 18:14:04

标签: postgresql performance

我一直认为大型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个子句的查询是否真的表现不佳?如果是这样的情况(假设列是索引等)。

1 个答案:

答案 0 :(得分:0)

解析器将列表中包含多个元素的IN表达式转换为=ANY表达式。

如果列上有B树索引,则可以始终使用它。

我能想到的唯一性能问题是优化器可能会错误地估计结果行的数量,并在索引扫描实际上更快时选择顺序扫描。

实验表明,优化程序为唯一列估计每个列表条目的一个结果行,并且最多包含表中的行数。这是一个合理的估计,但如果列表中有许多元素不匹配或存在重复,则估计值可能很高。