PostgreSQL-最大参数数在“中”;在;条款
在Postgres中,可以指定In子句,如下所示:PostgreSQL-最大参数数在“中”;在;条款,postgresql,Postgresql,在Postgres中,可以指定In子句,如下所示: SELECT * FROM user WHERE id IN (1000, 1001, 1002) 有人知道你可以通过的参数的最大数量吗?< P>你可能想考虑重构这个查询,而不是添加一个任意长的IDS列表…如果ID确实遵循示例中的模式,则可以使用范围: SELECT * FROM user WHERE id >= minValue AND id <= maxValue; 根据位于PostgreSQL的源代码,PostgreSQL
SELECT * FROM user WHERE id IN (1000, 1001, 1002)
有人知道你可以通过的参数的最大数量吗?
< P>你可能想考虑重构这个查询,而不是添加一个任意长的IDS列表…如果ID确实遵循示例中的模式,则可以使用范围:SELECT * FROM user WHERE id >= minValue AND id <= maxValue;
根据位于PostgreSQL的源代码,PostgreSQL没有明确限制参数的数量 以下是第870行的代码注释:
/*
* We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only
* possible if the inputs are all scalars (no RowExprs) and there is a
* suitable array type available. If not, we fall back to a boolean
* condition tree with multiple copies of the lefthand expression.
* Also, any IN-list items that contain Vars are handled as separate
* boolean conditions, because that gives the planner more scope for
* optimization on such clauses.
*
* First step: transform all the inputs, and detect whether any are
* RowExprs or contain Vars.
*/
在子句中传递给的元素数量没有限制。如果有更多的元素,它会把它看作数组,然后对于数据库中的每个扫描,它将检查它是否包含在数组中。这种方法没有那么好的可扩展性。不要使用IN子句,而是尝试使用带临时表的内部联接。有关更多信息,请参阅。使用内部连接比例以及查询优化器可以利用哈希连接和其他优化。而对于IN子句,优化器无法优化查询。我注意到这一变化至少加速了2倍 如果您有如下查询:
SELECT * FROM user WHERE id IN (1, 2, 3, 4 -- and thousands of another keys)
SELECT * FROM user WHERE id = ANY(VALUES (1), (2), (3), (4) -- and thousands of another keys)
如果重写查询,您可能会提高性能,如:
SELECT * FROM user WHERE id IN (1, 2, 3, 4 -- and thousands of another keys)
SELECT * FROM user WHERE id = ANY(VALUES (1), (2), (3), (4) -- and thousands of another keys)
查询计划
但如果尝试第二个查询:
explain select * from test where id = any (values (1), (2));
查询计划
我们可以看到,postgres构建临时表并与之连接这并不是对当前问题的真正回答,但也可能对其他人有所帮助 至少我可以看出,使用Posgresql的JDBC驱动程序9.1,可以传递到PostgreSQL后端的技术限制是32767个值(=Short.MAX_值) 这是对postgresql jdbc驱动程序的“从x中删除id(…100k值…)”的测试:
Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 100000
at org.postgresql.core.PGStream.SendInteger2(PGStream.java:201)
作为一个对Oracle DB更有经验的人,我也担心这个限制。我对一个查询进行了性能测试,该查询在-列表中的
中包含~10000个参数,通过实际将所有素数列为查询参数,从包含前100000个整数的表中获取最多100000个素数
我的结果表明,您不必担心查询计划优化器过载或在不使用索引的情况下获取计划,因为它会将查询转换为使用=ANY({…}::integer[])
,从而可以按预期利用索引:
-- prepare statement, runs instantaneous:
PREPARE hugeplan (integer, integer, integer, ...) AS
SELECT *
FROM primes
WHERE n IN ($1, $2, $3, ..., $9592);
-- fetch the prime numbers:
EXECUTE hugeplan(2, 3, 5, ..., 99991);
-- EXPLAIN ANALYZE output for the EXECUTE:
"Index Scan using n_idx on primes (cost=0.42..9750.77 rows=9592 width=5) (actual time=0.024..15.268 rows=9592 loops=1)"
" Index Cond: (n = ANY ('{2,3,5,7, (...)"
"Execution time: 16.063 ms"
-- setup, should you care:
CREATE TABLE public.primes
(
n integer NOT NULL,
prime boolean,
CONSTRAINT n_idx PRIMARY KEY (n)
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.primes
OWNER TO postgres;
INSERT INTO public.primes
SELECT generate_series(1,100000);
然而,这(相当陈旧)表明,在规划此类查询时仍有不可忽略的成本,所以请恕我直言。刚刚尝试过。答案是->
超出范围的整数作为2字节值:32768PostgreSQL的EXPLAIN
说它在(…)
asANY(“{…}”)::integer[])
。无论如何,@KiranJonnalagadda提高了性能(也许可以忽略不计)如果不需要内部工作的话。但是我听说博士后-9.3+的表现似乎是一样的。您所指的链接没有说明它在谈论什么DBMS。虽然我可以确认,在Oracle DB上,由于解析和规划此类查询的开销很大,使用临时表比在子句中使用组合或
和的查询提供了巨大的性能提升,但我无法确认Postgres 9.5的问题,请参见。OP询问了DB引擎的限制,但是为了寻找JDBC的局限性,我来到这里,这就是我想要的。所以有一个限制,但是,相当高。
Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 100000
at org.postgresql.core.PGStream.SendInteger2(PGStream.java:201)
-- prepare statement, runs instantaneous:
PREPARE hugeplan (integer, integer, integer, ...) AS
SELECT *
FROM primes
WHERE n IN ($1, $2, $3, ..., $9592);
-- fetch the prime numbers:
EXECUTE hugeplan(2, 3, 5, ..., 99991);
-- EXPLAIN ANALYZE output for the EXECUTE:
"Index Scan using n_idx on primes (cost=0.42..9750.77 rows=9592 width=5) (actual time=0.024..15.268 rows=9592 loops=1)"
" Index Cond: (n = ANY ('{2,3,5,7, (...)"
"Execution time: 16.063 ms"
-- setup, should you care:
CREATE TABLE public.primes
(
n integer NOT NULL,
prime boolean,
CONSTRAINT n_idx PRIMARY KEY (n)
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.primes
OWNER TO postgres;
INSERT INTO public.primes
SELECT generate_series(1,100000);