我在java程序中在postgresql数据库中执行查询,查询如下:
SELECT ... FROM table_name WHERE column_name IN("<list of values>");
问题是值列表是动态创建的,其大小没有限制,当此列表变得太大时,我收到PSQLException并显示消息:超出堆栈深度。 我的问题是如何确定在此异常发生之前我可以使用IN子句多少个参数?让我们说max_stack_depth是2MB,我可以用它来确定我可以用IN子句多少个参数吗?
答案 0 :(得分:4)
inner join
到values
表格
select ...
from
table_name
inner join
(values
(first_value), (second_value)
) s(column_name) using (column_name)
;
或者,更容易将字符串构建到unnested数组
select ...
from
table_name
inner join
unnest(
array[first_value, second_value]
) s(column_name) using (column_name)
;
答案 1 :(得分:2)
如果您使用的是7.4或更早版本,则取决于max_expr_depth
设置(或者我认为较新的max_stack_depth
)。
您可以随时查看它的值:
test=> SHOW max_expr_depth;
并改变
test=> SET max_expr_depth TO 10;
然后你可以操作这个值。
对于任何普通查询,默认值10000都足够高,但是 如果需要你可以提高它。 (但如果你把它提高得太高,你就跑了 堆栈溢出导致服务器崩溃的风险。)
这不是解决问题的最佳解决方案,但我相信它会回答您的问题。
答案 2 :(得分:1)
如果您担心in
子句中可能存在大量值,则可以使用临时表。
您创建一个临时表,其中包含一列和该列的索引。在查询之前,您将in
子句的数据作为临时表中的行。然后使用以下结构之一执行查询:
SELECT * FROM table_name WHERE column_name in (SELECT column_name FROM temptable);
SELECT * FROM table_name a JOIN temptable b ON (a.column_name = b.column_name);
SELECT * FROM table_name a WHERE EXISTS (SELECT * FROM temptable t WHERE a.column_name=t.column_name);
并行运行查询不会有问题:一个会话写入的临时表中的内容对任何其他会话都是不可见的。
这种方法的最大优点是,SQL解析不必生成所有值。查询的结构保持不变,您甚至可以使用预准备语句。这与索引的使用一起可以带来巨大的性能提升。