IN 子句中可以使用的标量的最大数量是多少?
What is the maximum number of scalars that can be used in an IN clause?
每当我使用一个小语句例如:
DELETE FROM c_ordertax WHERE (c_order_id,c_tax_id) IN ((183691598,1000862),(183691198,1000862));
它执行得很好......但是如果我执行一个冗长的语句来删除具有这些标量值的 18755 条记录,它会说 "max_stack_depth" 超出了......postgresql.conf 中的这个选项已经设置到 2MB,而抛出错误的查询甚至还不到 2MB,只有 300kb
注意:table
中没有附加触发器
关于其他查询,我注意到的一件事是,当我在 IN 子句中使用单个值时,例如:DELETE FROM c_ordertax WHERE (c_order_id) IN ((183691598),(183691198));
它们没有任何问题,无论查询可能有多长,它都能完美执行...
我目前的选择是:
- 我可以增加 "max_stack_depth" 值,但仅限于
8MB 并增加它会导致问题和 postgresql 服务器
无法重新启动...它只能正确重新启动该选项是
设置为小于 8MB 的值
- 我可以拆分这些语句,但它可能不优雅
解决方案,这也需要我知道最大标量值
可以容纳在单个语句中,如果字段数
标量值的增加,可以是值的总数
在单个语句中使用可以减少我担心...
所以我的问题是可以在 IN 子句中使用的标量值的最大数量是多少...如果标量值中的字段数量增加,是否有可用于确定最大值的公式可以使用的标量值的数量,例如:
5 values with 2 fields => ((1,2),(1,2),(1,2),(1,2),(1,2))
2 values with 3 fields => ((1,2,3),(1,2,3))
有数据库策划者遇到过这些问题吗?如果是这样,我该如何解决?
如果将标量值列表重写为 values()
列表,它应该可以工作:
DELETE FROM c_ordertax
using (
values
(183691598,1000862),
(183691198,1000862)
) as t(ord_id,tax_id)
WHERE c_order_id = t.ord_id
and c_tax_id = t.tax_id;
我在 values
列表中尝试了 10000 对,但没有抛出错误。然而,那是 Postgres 11。我现在没有可用的 9.3。
问题是 IN
对列表在解析阶段像这样转换:
EXPLAIN DELETE FROM large WHERE (id, id) IN ((1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Delete on large (cost=0.00..39425.00 rows=1 width=6)
-> Seq Scan on large (cost=0.00..39425.00 rows=1 width=6)
Filter: (((id = 1) AND (id = 1)) OR ((id = 2) AND (id = 2)) OR ((id = 3) AND (id = 3)) OR ((id = 4) AND (id = 4)) OR ((id = 5) AND (id = 5)))
(3 rows)
如果列表由标量组成,PostgreSQL 可以做得更好:
EXPLAIN DELETE FROM large WHERE id IN (1, 2, 3, 4, 5);
QUERY PLAN
---------------------------------------------------------------
Delete on large (cost=0.00..20675.00 rows=5 width=6)
-> Seq Scan on large (cost=0.00..20675.00 rows=5 width=6)
Filter: (id = ANY ('{1,2,3,4,5}'::integer[]))
(3 rows)
第二个版本将 运行 包含大列表,但第一个版本将 运行 在递归解析过程中达到限制。
我不确定这是否可以改进,但它可能不被视为值得花很多精力的案例。您随时可以像 "a_horse_with_no_name" 建议的那样重写您的查询。
通常,如果您有像这样的长 IN
列表,您可能做错了什么,例如尝试在数据库外执行连接。
每当我使用一个小语句例如:
DELETE FROM c_ordertax WHERE (c_order_id,c_tax_id) IN ((183691598,1000862),(183691198,1000862));
它执行得很好......但是如果我执行一个冗长的语句来删除具有这些标量值的 18755 条记录,它会说 "max_stack_depth" 超出了......postgresql.conf 中的这个选项已经设置到 2MB,而抛出错误的查询甚至还不到 2MB,只有 300kb
注意:table
中没有附加触发器关于其他查询,我注意到的一件事是,当我在 IN 子句中使用单个值时,例如:DELETE FROM c_ordertax WHERE (c_order_id) IN ((183691598),(183691198));
它们没有任何问题,无论查询可能有多长,它都能完美执行...
我目前的选择是:
- 我可以增加 "max_stack_depth" 值,但仅限于 8MB 并增加它会导致问题和 postgresql 服务器 无法重新启动...它只能正确重新启动该选项是 设置为小于 8MB 的值
- 我可以拆分这些语句,但它可能不优雅 解决方案,这也需要我知道最大标量值 可以容纳在单个语句中,如果字段数 标量值的增加,可以是值的总数 在单个语句中使用可以减少我担心...
所以我的问题是可以在 IN 子句中使用的标量值的最大数量是多少...如果标量值中的字段数量增加,是否有可用于确定最大值的公式可以使用的标量值的数量,例如:
5 values with 2 fields => ((1,2),(1,2),(1,2),(1,2),(1,2))
2 values with 3 fields => ((1,2,3),(1,2,3))
有数据库策划者遇到过这些问题吗?如果是这样,我该如何解决?
如果将标量值列表重写为 values()
列表,它应该可以工作:
DELETE FROM c_ordertax
using (
values
(183691598,1000862),
(183691198,1000862)
) as t(ord_id,tax_id)
WHERE c_order_id = t.ord_id
and c_tax_id = t.tax_id;
我在 values
列表中尝试了 10000 对,但没有抛出错误。然而,那是 Postgres 11。我现在没有可用的 9.3。
问题是 IN
对列表在解析阶段像这样转换:
EXPLAIN DELETE FROM large WHERE (id, id) IN ((1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Delete on large (cost=0.00..39425.00 rows=1 width=6)
-> Seq Scan on large (cost=0.00..39425.00 rows=1 width=6)
Filter: (((id = 1) AND (id = 1)) OR ((id = 2) AND (id = 2)) OR ((id = 3) AND (id = 3)) OR ((id = 4) AND (id = 4)) OR ((id = 5) AND (id = 5)))
(3 rows)
如果列表由标量组成,PostgreSQL 可以做得更好:
EXPLAIN DELETE FROM large WHERE id IN (1, 2, 3, 4, 5);
QUERY PLAN
---------------------------------------------------------------
Delete on large (cost=0.00..20675.00 rows=5 width=6)
-> Seq Scan on large (cost=0.00..20675.00 rows=5 width=6)
Filter: (id = ANY ('{1,2,3,4,5}'::integer[]))
(3 rows)
第二个版本将 运行 包含大列表,但第一个版本将 运行 在递归解析过程中达到限制。
我不确定这是否可以改进,但它可能不被视为值得花很多精力的案例。您随时可以像 "a_horse_with_no_name" 建议的那样重写您的查询。
通常,如果您有像这样的长 IN
列表,您可能做错了什么,例如尝试在数据库外执行连接。