我发现我自己有时需要根据id或其他变量的列表选择不同表的许多项。考虑到这个列表可以包含数千个元素,对我来说过滤器不会变成n*m查询是很重要的。我经历过在某些情况下postgres可以快速查找,有时不能,例如,如果我通过主键进行过滤,当它进行缓慢过滤时,我通常通过创建IN
查询表并将其与表连接以进行过滤来解决它。
但是现在我又回到了这个问题上,我真的很想听听有人能不能帮我建立一些直觉,什么时候我应该假设使用查找,什么时候使用哈希表。
在我目前的工作中,我们使用的是postgres 15,但我的大部分经验都来自postgres 10,所以可能会有一些旧版本的坏习惯。
3条答案
按热度按时间polkgigr1#
v14引入了一个优化(commit 50 e17 ad 281 b8 d1c 1b)对大型IN列表使用哈希表,而不是对每个候选行在IN列表上进行线性搜索。因此,从那时起,你不应该得到O(nm)的行为。可能会有一些极端情况,就像如果在-列表是动态计算的,或者类型不完全兼容。查询计划中没有任何内容表明正在进行此优化(除了降低的成本估计)。
即使在v14之前,如果被测试的列被索引,那么它可以为列表的每个成员跳一次索引,从而避免O(nm)的行为。在幕后,这是一个循环,但在查询计划中,它只是作为索引扫描呈现,索引条件为
Index Cond: (col1 = ANY('{...
31moq8wy2#
为什么要假设你可以
explain analyze verbose
。如果没有看到它取代了什么以及如何取代的例子,很难评论为什么IN
* 工作得如此之好 *。即使你有足够的直觉去相信它,如果你 * 信任,但要验证 *,你仍然会更好。服务器配置,索引设置,表大小,流量以及
vacuum analyze
d的频率都可以影响规划器的结果,并且它可以改变版本。在这种情况下,所有人类的直觉注定是不可靠的,并且很快就会过时。也就是说,here are some 1M-row tests at db<>fiddle,这里有一些comparisons of
in
,any
,exists
,join
behaviour,这里有some more, more visual。hk8txs483#
以前我在某个时候使用
column = ANY (VALUES (...), ...)
,而不是使用IN
进行N次批处理请求,因为它更快(基本上它创建一个临时表,然后与它连接),但看起来在Postgres 15中,这不是一个案例,即使有2000个值,常规的IN
也比值列表过滤器快2倍。(但可能在某个N时,它仍然比IN
快)将
sku_test
表设置为字符串
大约有22 k条记录
型
导致
型
和
型
导致
型
我在生产数据库上看到了类似的结果,其中包含活表和过滤列上的索引。
但同样,自己衡量总是更好的。
upd:作为@FrankHeikens回复的示例,这里是一个带有文本列和唯一索引的1 M表的示例,以及~ 10 k过滤器
型
IN
个型
导致
型
使用
VALUES
型