每当我使用一个小语句时,例如:
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
注意:表中没有附加触发器
我注意到有关其他查询的一件事是,当我在IN子句中使用单个值时,例如:DELETE FROM c_ordertax WHERE (c_order_id) IN ((183691598),(183691198));
他们没有任何问题,无论查询多么冗长,它都可以完美地执行...
我目前的选择是:
所以我的问题是可以在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))
任何数据库Mastermind都遇到过这些问题?如果是这样我该如何解决?
如果您将标量值列表重写为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
列表,你可能做错了,比如尝试在数据库外执行连接。