intagg
模块提供了一个整数聚合器和一个枚举器。intagg
现在已经过时了,因为有一些内置函数提供了它功能的超集。然而,该模块仍然作为内置函数的兼容性包装器提供。
聚合器是一个聚合函数 int_array_aggregate(integer)
,它产生一个整数数组,其中包含它被馈送的所有整数。这是 array_agg
的包装器,它对任何数组类型执行相同的操作。
枚举器是一个函数 int_array_enum(integer[])
,它返回 setof integer
。它本质上是聚合器的反向操作:给定一个整数数组,将其展开为一组行。这是 unnest
的包装器,它对任何数组类型执行相同的操作。
许多数据库系统都有多对多表的概念。这种表通常位于两个索引表之间,例如
CREATE TABLE left_table (id INT PRIMARY KEY, ...); CREATE TABLE right_table (id INT PRIMARY KEY, ...); CREATE TABLE many_to_many(id_left INT REFERENCES left_table, id_right INT REFERENCES right_table);
它通常像这样使用
SELECT right_table.*
FROM right_table JOIN many_to_many ON (right_table.id = many_to_many.id_right)
WHERE many_to_many.id_left = item
;
这将返回左侧表中条目的右侧表中的所有项目。这是 SQL 中非常常见的结构。
现在,如果 many_to_many
表中的条目数量非常大,这种方法可能会很麻烦。通常,像这样的连接会导致索引扫描和为特定左侧条目的表中每个右侧条目进行提取。如果您有一个非常动态的系统,那么您无能为力。但是,如果您有一些相当静态的数据,则可以使用聚合器创建一个汇总表。
CREATE TABLE summary AS SELECT id_left, int_array_aggregate(id_right) AS rights FROM many_to_many GROUP BY id_left;
这将创建一个表,其中每个左侧项目一行,以及一个右侧项目数组。现在,如果没有某种使用数组的方法,这是毫无用处的;这就是为什么有数组枚举器的原因。你可以这样做
SELECT id_left, int_array_enum(rights) FROM summary WHERE id_left = item
;
上面使用 int_array_enum
的查询产生与以下相同的结果
SELECT id_left, id_right FROM many_to_many WHERE id_left = item
;
不同之处在于,针对汇总表的查询只需要从表中获取一行,而直接针对 many_to_many
的查询必须索引扫描并为每个条目获取一行。
在一个系统中,一个 EXPLAIN
显示一个成本为 8488 的查询降低到成本为 329。原始查询是涉及 many_to_many
表的连接,它被替换为
SELECT id_right, count(id_right) FROM
( SELECT id_left, int_array_enum(rights) AS id_right
FROM summary
JOIN (SELECT id FROM left_table
WHERE id = item
) AS lefts
ON (summary.id_left = lefts.id)
) AS list
GROUP BY id_right
ORDER BY count DESC;
如果您在文档中看到任何不正确、与特定功能的经验不符或需要进一步澄清的内容,请使用此表单报告文档问题。