F.17. intagg

intagg模块提供了一个整数聚合器和一个枚举器。 intagg现在已过时,因为有内置的函数为其功能提供了超集。但是,该模块仍作为内置函数的兼容性包装提供。

F.17.1. Functions

聚合器是一个聚合函数int_array_aggregate(integer),该函数生成一个整数数组,该数组恰好包含它所馈入的整数。这是array_agg的包装,它对任何数组类型都执行相同的操作。

枚举器是返回_1 的函数int_array_enum(integer[])。本质上,这是聚合器的反向操作:给定整数数组,将其扩展为一组行。这是对unnest的包装,它对任何数组类型都执行相同的操作。

F.17.2. sample 用途

许多数据库系统都有一对多表的概念。这样的表通常位于两个索引表之间,例如:

CREATE TABLE left (id INT PRIMARY KEY, ...);
CREATE TABLE right (id INT PRIMARY KEY, ...);
CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right);

通常这样使用:

SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
  WHERE one_to_many.left = item;

这将返回右侧表中的所有项目,以在左侧表中提供一个条目。这是 SQL 中非常常见的构造。

现在,此方法可能很麻烦,因为one_to_many表中的条目非常多。通常,这样的联接会导致索引扫描和表中每个右手条目的读取(针对特定左手条目)。如果您有一个非常动态的系统,那么您将无能为力。但是,如果您有一些相当静态的数据,则可以使用聚合器创建汇总表。

CREATE TABLE summary AS
  SELECT left, int_array_aggregate(right) AS right
  FROM one_to_many
  GROUP BY left;

这将创建一个表,其中每个左边的项目都有一行,而右边的项目则是一个数组。现在,如果没有某种使用数组的方法,这将毫无用处。这就是为什么有一个数组枚举器的原因。你可以做

SELECT left, int_array_enum(right) FROM summary WHERE left = item;

上面使用int_array_enum的查询产生的结果与

SELECT left, right FROM one_to_many WHERE left = item;

区别在于,针对汇总表的查询仅需从表中获取一行,而针对one_to_many的直接查询则必须索引扫描并为每个条目获取一行。

在一个系统上,EXPLAIN显示成本为 8488 的查询减少为 329.原始查询是涉及one_to_many表的联接,被替换为:

SELECT right, count(right) FROM
  ( SELECT left, int_array_enum(right) AS right
    FROM summary JOIN (SELECT left FROM left_table WHERE left = item) AS lefts
         ON (summary.left = lefts.left)
  ) AS list
  GROUP BY right
  ORDER BY count DESC;