我需要创建一个Postgres 9.1 PL / pgSQL的存储过程,除了其它参数之外,采用值序列,在我的数据库中的列中的一个直接引用值。 据我所知道的,规范的方法在Postgres的做,这是一个数组 。
当然,这是一个相当基本任务。 我的问题是可扩展性:我的代码基本上工作,但一旦通过序列得到较大(如在价值几百或上千)表现不好:
我的存储过程中即使是很简单的SELECT语句使用数组形式
SELECT <some columns>
FROM <some tables>
WHERE <some other select criteria>
AND <column with values selected by array parameter>
IN (SELECT * FROM unnest(<array parameter>))
需要几秒钟才能执行,即使数据库不是很大但并有只有几十数组中的值。
我的第一个怀疑的是, unnest(...)
的问题,但只能从与数组参数引用的列的表中选择是非常快:
SELECT <some columns>
FROM <table with column ref'd in array parameter>
WHERE <column with values selected by array parameter>
IN (SELECT * FROM unnest(<array parameter>))
只需要几毫秒。
我的问题 :
- 是否有使用数组作为参数的方法吗?
- 我怎样才能让我的查询有更好的表现?
我怎样才能让我的查询有更好的表现?
我希望更快的性能,如果你重写查询
SELECT <some columns>
FROM <some tables>
WHERE <some other select criteria>
AND <column with values selected by array parameter>
IN (SELECT * FROM unnest(<array parameter>));
至:
SELECT <some columns>
FROM (SELECT unnest(<array parameter>) AS param) x
JOIN <filtered table> ON <filter column> = x.param
JOIN <other table> ON <join criteria>
WHERE <some other select criteria>;
这听起来像查询规划选择次优计划,误判您的其他成本WHERE
条件相比,IN子句。 通过将其转化为明确的JOIN
子句,你应该得到更好的查询计划。
一般情况下, JOIN
小号往往比大快IN
PostgreSQL中的条款。
是否有使用数组作为参数的方法吗?
是。
您可以创建临时表,填写并运行一个查询加入反对。
CREATE TEMP TABLE x(id int);
INSERT INTO x VALUES
(1), (2), (17), (18);
SELECT <some columns>
FROM x
JOIN <filtered table> ON <filter column> = x.id
JOIN <other table> ON <join criteria>
WHERE <some other select criteria>;
或者,但速度更快,使用CTE为了同样的目的:
WITH x(id) AS (
VALUES (1::int), (2), (17), (18) -- type-cast on first element is enough
)
SELECT <some columns>
FROM x
JOIN <filtered table> ON <filter column> = x.id
JOIN <other table> ON <join criteria>
WHERE <some other select criteria>;
只要你想使用的功能,一个数组参数,嵌套的内部将是我的选择,太多。 你也可以使用CTE在我的最后一个例子在函数内部,只是UNNEST(ARR),而不是VALUES子句。