F.18. intagg
intagg
模块提供了一个整数聚合器和一个枚举器。 intagg
现在已过时,因为有内置的函数为其功能提供了超集。但是,该模块仍作为内置函数的兼容性包装提供。
F.18.1. Functions
聚合器是一个聚合函数int_array_aggregate(integer)
,该函数生成一个整数数组,该数组恰好包含它所馈入的整数。这是array_agg
的包装,它对任何数组类型都执行相同的操作。
枚举器是返回_1 的函数int_array_enum(integer[])
。本质上,这是聚合器的反向操作:给定整数数组,将其扩展为一组行。这是对unnest
的包装,它对任何数组类型都执行相同的操作。
F.18.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;