Postgresql数组&&运营商执行速度低于预期

时间:2017-06-22 08:10:21

标签: performance postgresql postgresql-9.6

样本数据

我需要在包含整数数组的列上加入2个表。

CREATE TABLE table_array_1 (key1 int, values1 int[]);
CREATE TABLE table_array_2 (key2 int, values2 int[]);

一个表包含少量行但数组大小:

DO $function$
DECLARE
  i int := 0;
BEGIN
  WHILE i < 100 LOOP
      INSERT INTO table_array_1 (key1, values1) values(random(1, i), (SELECT array_agg(random(3000000, 4000000)) FROM (SELECT generate_series(1, random(1, 2000))) lp));
      i := i + 1;
  END LOOP;
END;
$function$

第二个表有更多行,但是数组大小很小:

DO $function$
DECLARE
  i int := 0;
BEGIN
  WHILE i < 1000 LOOP
      INSERT INTO table_array_2 (key2, values2) values(random(1, i), (SELECT array_agg(random(3000000, 4000000)) FROM (SELECT generate_series(1, random(1, 50))) lp));
      i := i + 1;
  END LOOP;
END;
$function$

函数random(int,int)返回范围内的随机整数:

CREATE OR REPLACE FUNCTION random(int, int)
 RETURNS int
 LANGUAGE sql
AS $function$
   SELECT ($1 + ($2 - $1) * random())::int;
$function$

测试

我最初尝试加入他们explain

SELECT t1.key1, t2.key2
  FROM table_array_1 t1
  JOIN table_array_2 t2 ON t2.values2 && t1.values1

但它比explain慢得多(大约100倍):

SELECT DISTINCT t1.key1, t2.key2
  FROM (SELECT key1, unnest(values1) AS values1 FROM table_array_1) t1
  JOIN (SELECT key2, unnest(values2) AS values2 FROM table_array_2) t2
    ON t2.values2 = t1.values1

这些表上没有索引,使用GIN成本太高而无法使用。 GiST没有改进它。这假设我会使用intarray扩展名。

问题

为什么unnest + distinct要快得多?

我可以提高数组比较运算符方法的性能,还是使用其他不会涉及unnest + distinct的其他方法?我正在寻找性能改进,常识告诉我这两个操作应该更慢。

1 个答案:

答案 0 :(得分:0)

我认为性能差异并非真正来自JOIN vs UNNEST,而是来自您正在检查的情况。

&&数组操作数非常耗费资源,因为它需要检查数组中任何两个元素是否重叠(特别是当数组被NULL“污染”时值)。虽然普通=操作数可能在字节级工作,因此速度要快得多。

PS:根据您的Postgres版本,您的引擎可能还没有正确优化查询计划。 (this, for 9.0, is quite an outstanding example)。