2

我有 postgresql 查询,我在其中检查两个数组的交集长度。我的查询的非常简化版本如下所示:

SELECT array_length(users.array & Array[1,2,3,4]) from users;

它是更大查询的一部分,但这在这里并不重要。它在我的本地数据库上运行良好,但在 heroku 上,intarray 扩展名未列入白名单。

我发现了与数组相交的简单函数,但与&运算符相比,它相当慢。

CREATE OR REPLACE FUNCTION array_intersect(anyarray, anyarray)
RETURNS anyarray AS $$
  SELECT ARRAY( SELECT * FROM UNNEST( $1 ) WHERE UNNEST = ANY( $2 ) );
$$ LANGUAGE sql;

在我的表的大约 2000 条记录上,使用&运算符需要大约50ms和使用上面的函数需要大约150ms。我想尽可能多地比较记录,但这个函数的扩展性不如'&'运算符。

有什么方法可以更快地做到这一点或将 intarray 添加到heroku?

4

1 回答 1

1

猜猜它可能取决于您的查询的其余部分,以及它需要如何优化。

我的第一次尝试是使用unnestand intersect... 创建所有昆虫长度的 CTE,然后在需要的地方从我的主要表达式中的 CTE 中获取值...类似于以下内容:

WITH merged AS (
    SELECT * FROM unnest(ARRAY[1,2,3]) 
    INTERSECT 
    SELECT * FROM unnest(ARRAY[1])
) 
SELECT count(*) as length FROM merged;

如果这不合适,我会尝试一个函数(就像你一样),但由于我只对长度感兴趣,我会让函数返回它(以避免不必要的转换为数组并返回):

CREATE OR REPLACE FUNCTION array_count_intersects(anyarray, anyarray)
RETURNS bigint AS $$
    SELECT count(*) FROM (
        SELECT * FROM UNNEST($1) WHERE UNNEST = ANY($2)
    ) as merg;
$$ LANGUAGE sql;

SELECT array_count_intersects(ARRAY[1,2,3], ARRAY[1]);

如果这仍然不够好,那么我会考虑创建一个中间表来存储/缓存在数据更改时通过触发器更新的相交数组的长度,然后使用这个中间表来查找我需要的长度我的主要查询根本不需要执行联合。

于 2013-04-05T11:22:51.627 回答