如何在两个大型 postgreSQL 表上批量运行外连接?

Posted

技术标签:

【中文标题】如何在两个大型 postgreSQL 表上批量运行外连接?【英文标题】:How can I run an outer join on two large postgreSQL tables in batches? 【发布时间】:2020-10-06 19:50:03 【问题描述】:

我有两个包含数百万行的表。他们共享一个共同的电子邮件地址。他们不共享任何其他字段。

我有一个运行良好的连接操作。

select r.*,l.* from righttable r full outer join lefttable l on r.email=l.email 

但是,结果集包含数百万行,这使我的服务器内存不堪重负。如何运行一次只从每个表中提取有限数量的行并最终访问两个表中的所有行的连续查询?

此外,在收到结果集后,我们的服务器可能会在其中一个或两个表中进行一些插入。恐怕这可能会使跟踪每个连续查询中的偏移量变得复杂。也许这不是问题。我无法绕开它。

【问题讨论】:

如果你想要一个内部连接,我会有一个很好的答案...... 您之前的答案(我看到您已删除)建议使用 Like 子句。我知道这将如何工作。正如我想象的你在发布后考虑的那样,这只有在电子邮件以“a”开头的行数与电子邮件以“b”开头的行数大致相同的情况下才有效,等等所有其他字母。但这并不能保证,如果碰巧出现这种情况,查询可能仍会返回太多结果,我们的服务器无法处理。 不,我删除答案的原因是它不适用于外连接。可以改变确切的LIKE 条件以获得相等的分区,这不是基本问题。 【参考方案1】:

我认为您不能分批执行此操作,因为它不知道在不查看所有数据的情况下要构造哪些行来完成“FULL OUTER”。如果您知道在您工作时没有人对表进行更改,则可以通过在单独的查询中选择仅左侧元组、仅右侧元组和内部元组来解决此问题。

但是,它不应消耗服务器上的所有内存(假设您的意思是 RAM,而不是磁盘空间),因为它应该使用临时文件而不是 RAM 来获取所需的大量存储空间(尽管内存存在一些问题用于巨大的哈希连接,所以你可以试试set enable_hashjoin=off)。

客户端可能会使用太多内存,因为它可能会尝试一次将整个结果集读入客户端 RAM。有一些方法可以解决这个问题,但它们可能不涉及操纵 JOIN 本身。您可以使用游标从单个结果流中批量读取,或者您可以使用 \copy 将结果输出到磁盘,然后使用 GNU split 之类的东西。

【讨论】:

以上是关于如何在两个大型 postgreSQL 表上批量运行外连接?的主要内容,如果未能解决你的问题,请参考以下文章

优化大型表上的 SQL 连接

PostgreSQL 上的 EF Core 批量删除

在 PostgreSql 中批量更新或删除哪个更高效?

如果使用 Jdbc 在 PostgreSQL 中有太多行,如何停止大型查询?

如何提高大型表上基于日期的查询性能?

连接表上的索引