【问题标题】:What is the most performant way to rewrite a large IN clause?重写大型 IN 子句的最高效方法是什么?
【发布时间】:2018-10-09 01:12:36
【问题描述】:

我使用 go 和 gorm 编写了一个 API,它在我们的数据库上运行计算并返回结果。

在使用聚合时,我刚刚达到了 IN 条件的参数限制。示例查询:

SELECT SUM(total_amount) from Table where user_id in(...70k parameters) group by user_id

我当前的一个边缘案例有 > 65535 个用户 ID,因此我的 Postgres 客户端抛出错误:

got 66037 parameters but PostgreSQL only supports 65535 parameters

我不确定解决此问题的最佳方法是什么。一个可以处理这种边缘情况的大量参数,同时不会影响我的典型用例。我是否将 id 分块并遍历将其存储在内存中的多个查询,直到获得所需的所有数据?使用ANY(VALUES)...

显然,从查询中我对 Postgres 的了解非常有限,因此非常感谢任何帮助。

【问题讨论】:

  • 您使用所需的 user_id 创建一个表并进行左连接

标签: sql postgresql go go-gorm sql-in


【解决方案1】:

您可以将user_id IN (value [, ...]) 替换为以下之一:

user_id IN (subquery)
user_id = ANY (subquery)
user_id = ANY (array expression)

子查询和数组都没有表现出相同的限制。最短的输入语法是:

user_id = ANY ('{1,2,3}'::int[])  -- make array type match type of user_id

详细信息和更多选项:

或者您可以创建一个(临时)表tmp_usr(user_id int),导入到它,可能使用SQL COPY 或psql \copy 而不是INSERT 以获得最佳性能非常大的集合,然后加入到表中,例如:

SELECT SUM(total_amount)
FROM   tbl
JOIN   tmp_usr USING (user_id)
GROUP  BY user_id;

顺便说一句,GROUP BY user_id 不包括 user_idSELECT 列表中看起来很可疑。可能是一个简化的示例查询。

【讨论】:

  • 加入 values 子句而不是 IN 是另一种有时更快的选项。参见例如here
  • 是的,VALUES 表达式是子查询的一种形式,这对于大集合通常更快。主题的变体:在子查询中传递一个数组和unnest。上面链接答案中的每个信息和更多链接。
猜你喜欢
  • 2018-05-01
  • 1970-01-01
  • 2011-12-06
  • 2014-10-13
  • 2011-02-21
相关资源
最近更新 更多