我需要在包含整数数组的列上加入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
的其他方法?我正在寻找性能改进,常识告诉我这两个操作应该更慢。
答案 0 :(得分:0)
我认为性能差异并非真正来自JOIN
vs UNNEST
,而是来自您正在检查的情况。
&&
数组操作数非常耗费资源,因为它需要检查数组中任何两个元素是否重叠(特别是当数组被NULL
“污染”时值)。虽然普通=
操作数可能在字节级工作,因此速度要快得多。
PS:根据您的Postgres版本,您的引擎可能还没有正确优化查询计划。 (this, for 9.0, is quite an outstanding example)。