【问题标题】:Difference between ANY(ARRAY[..]) vs ANY(VALUES (), () ..) in PostgreSQLPostgreSQL 中 ANY(ARRAY[..]) 与 ANY(VALUES (), () ..) 之间的区别
【发布时间】:2020-11-15 06:32:14
【问题描述】:

我正在尝试对 id 进行查询优化。不确定我应该使用哪一种方式。下面是使用explain 的查询计划,成本方面看起来很相似。

1. explain (analyze, buffers) SELECT * FROM table1 WHERE id = ANY (ARRAY['00e289b0-1ac8-451f-957f-e00bc289148e'::uuid,...]);

QUERY PLAN:
    Index Scan using table1_pkey on table1  (cost=0.42..641.44 rows=76 width=835) (actual time=0.258..2.603 rows=76 loops=1)
    Index Cond: (id = ANY ('{00e289b0-1ac8-451f-957f-e00bc289148e,...}'::uuid[]))
    Buffers: shared hit=231 read=73
    Planning Time: 0.487 ms
    Execution Time: 2.715 ms)


2. explain (analyze, buffers) SELECT * FROM table1 WHERE id = ANY (VALUES ('00e289b0-1ac8-451f-957f-e00bc289148e'::uuid),...);

QUERY PLAN:
Nested Loop  (cost=1.56..644.10 rows=76 width=835) (actual time=0.058..0.297 rows=76 loops=1)
   Buffers: shared hit=304
   ->  HashAggregate  (cost=1.14..1.90 rows=76 width=16) (actual time=0.049..0.060 rows=76 loops=1)
         Group Key: "*VALUES*".column1
         ->  Values Scan on "*VALUES*"  (cost=0.00..0.95 rows=76 width=16) (actual time=0.006..0.022 rows=76 loops=1)
   ->  Index Scan using table1_pkey on table1  (cost=0.42..8.44 rows=1 width=835) (actual time=0.002..0.003 rows=1 loops=76)
         Index Cond: (id = "*VALUES*".column1)
         Buffers: shared hit=304
Planning Time: 0.437 ms
Execution Time: 0.389 ms

看起来VALUES () 做了一些散列和连接以提高性能,但不确定。

注意:在我的实际用例中,iduuid_generate_v4() e.x。 d31cddc0-1771-4de8-ad41-e6c568b39a5d 但该列可能不会被索引。 另外,我有一张5-10 million records 的表格。 哪种方式查询性能更好?

【问题讨论】:

  • 您的示例中的数据量太小,以至于查询计划中的这种差异并不重要。除非您的数据更大,否则没有理由担心。看起来VALUES() 的使用需要一个额外的步骤来删除重复项。这对您的实际查询可能有用也可能没用。
  • 我有一个包含 5-10 百万条记录的表。在问题中添加了此信息。
  • 请使用这两个查询对该表运行explain (analyze, buffers),然后edit您的问题并添加这些执行计划。
  • 用实际查询结果更新了问题。
  • 我不明白您所说的“可能不是这样的索引”是什么意思。您的计划清楚地表明您有一个包含id 列的索引。两个计划之间的性能差异仅是由于第一个计划必须从磁盘中读取一些块 (read=73) 造成的,而在第二个计划中,所有内容都在缓冲区缓存中。如果您多次运行第一个,您可能会得到与第二个相同的执行时间。在任一情况下,两者都处理相同数量的块(304)。如果所有内容都被缓存,我实际上希望第一个计划更快。

标签: sql postgresql query-optimization where-clause


【解决方案1】:

这两种选择似乎都很合理。但是,我建议避免投射您过滤的列。相反,您应该将文字值转换为 uuid:

SELECT * 
FROM table1 
WHERE id = ANY (ARRAY['00e289b0-1ac8-451f-957f-e00bc289148e'::uuid, ...]);

这应该允许数据库利用列 id 上的索引。

【讨论】:

  • VALUES ('00e289b0-1ac8-451f-957f-e00bc289148e') 方法不需要强制转换。考虑到执行时间相差 1 秒,有没有其他方法可以验证或选择其中任何一个?
  • @impossible:当你投射数组时会发生什么?那么执行计划是什么?
  • @a_horse_with_no_name :在两个查询中都添加了 ::uuid。请注意,id 列可能不是这样的索引
猜你喜欢
  • 1970-01-01
  • 2018-08-23
  • 2021-01-30
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
相关资源
最近更新 更多