例如,每当我使用一个小语句:
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))
任何数据库策划者都遇到过这些问题吗?如果是这样,我该如何解决?
答案 0 :(得分:2)
如果将标量值列表重写为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版本。
答案 1 :(得分:1)
问题是xxx.xx.x.xx - - [05/Apr/2019 10:00:15] "POST /diff HTTP/1.1" 400 -
对列表在解析阶段会像这样转换:
IN
如果列表包含标量,则PostgreSQL可以做得更好:
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)
第二个版本将使用较大的列表运行,但第一个版本将在递归解析过程中遇到限制。
我不确定是否可以改进,但是可能不值得花很多精力在案例上。您始终可以像建议的“ a_horse_with_no_name”一样重写查询。
通常,如果您有很长的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)
这样的列表,则您可能做错了某些事情,例如尝试在数据库外部执行联接。