Postgres的:如何有效地使用数组作为存储过程的参数?(Postgres: How to use

2019-09-30 04:06发布

我需要创建一个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>))

只需要几毫秒。

我的问题

  1. 是否有使用数组作为参数的方法吗?
  2. 我怎样才能让我的查询有更好的表现?

Answer 1:

我怎样才能让我的查询有更好的表现?

我希望更快的性能,如果你重写查询

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子句。



文章来源: Postgres: How to use arrays as stored procedure parameters efficiently?