在不使用 @> 和 postgreSQL 的情况下查找包含另一个数组子集的数组

Posted

技术标签:

【中文标题】在不使用 @> 和 postgreSQL 的情况下查找包含另一个数组子集的数组【英文标题】:Finding arrays that contain a subset of another array without using @> with postgreSQL 【发布时间】:2014-02-05 12:44:11 【问题描述】:

我有一张带有1.5 MM 记录的表格。每条记录都有一个row number 和一个array,数组中的元素介于1 and 1,000 之间。我正在尝试查找属于较大数组子集的所有数组。

当我使用下面的代码时,我得到 ERROR: statement requires more resources than resource queue allowed (可能是因为有超过一万亿种可能的组合)

select
   a.array as dup
from
   table a
left join
    table  b
on
  b.array @> a.array 
  and a.row_number <> b.row_number

除了使用@&gt;之外,有没有更有效的方法来识别哪些数组是其他数组的子集并将它们标记为删除?

【问题讨论】:

您是否尝试过在数组列上创建 GIN 索引? 我们的数据库不支持 GIN 索引 - 它位于 Greenplum 版本上。 如果您想知道与此类数据库相关的 row_number - 它是使用任意顺序手动分配的,但每次我从表中提取数据时总是相同的。跨度> 【参考方案1】:

您的示例代码表明您只对在表的另一行中查找作为 any 其他数组的子集的数组感兴趣。

但是,您的带有 JOIN 的查询会返回所有组合,可能会产生相乘的结果。

尝试使用EXISTS 半联接,只返回符合条件的行一次

SELECT a.array as dup
FROM   table a
WHERE  EXISTS (
   SELECT 1
   FROM   table b
   WHERE  a.array <@ b.array
   AND    a.row_number <> b.row_number
   );

使用这种形式,Postgres 可以在找到第一个匹配项后立即停止迭代行。如果这也不会通过,请尝试分区您的查询。添加一个类似的子句

AND table_id BETWEEN 0 AND 10000

并遍历表。在这种情况下应该是有效的。

除此之外:很遗憾您的衍生产品 (Greenplum) 似乎不支持 GIN 索引,这会使此操作更快。 (不过,索引本身会很大)

【讨论】:

感谢您的建议。不幸的是,只有当我将 table_id 设置为 AND table_id BETWEEN 0 AND 500 时才使用 table_id,这意味着很多迭代。通过使用 LIMIT 100000 和我的语句结束,我能够说服系统运行我的代码,然而,这意味着迭代次数要少得多。【参考方案2】:

好吧,如果没有索引的适当支持,我看不出如何在单个声明性 SQL 语句中有效地执行此操作。我不知道这对 GIN 索引的效果如何,但使用 GIN 索引肯定会避免需要比较每一对可能的行。

我要做的第一件事是仔细调查您可以使用的索引类型,并尝试根据需要创建一个。

如果这不起作用,从程序上讲,我首先想到的是对所有数组进行排序,然后将行排序为数组上的分级字典顺序。然后从最短的数组开始,按如下方式向上工作:例如对于 [1,4,9],检查所有长度

我相信您可以稍微调整一下这个算法,尤其是根据所涉及数据的特定性质。如果有更好的算法,我不会感到惊讶。这只是我想到的第一件事。您可能可以从该算法向后工作到您想要的 SQL,或者您可能必须转储表以进行客户端处理,或两者兼而有之。

【讨论】:

以上是关于在不使用 @> 和 postgreSQL 的情况下查找包含另一个数组子集的数组的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql:在不返回任何记录的视图上选择查询

如何在不明确指定主键的情况下使用 Dapper Extensions 将对象插入 PostGreSql?

在不相关列上的 Postgresql 错误中选择 Distinct

在不使用 S3 存储桶的情况下将数据从远程服务器的 .gz 文件加载到 redshift 的 postgresql 实例?

如何在不指定数据库名称的情况下连接到 PostgreSQL?

PostgreSQL:如何在不延迟插入响应的情况下执行插入触发器?