我只是在回顾一些为8.4之前的PostgreSQL编写的旧代码,我发现确实很不错。我记得以前有一个自定义函数来执行某些操作,但我忘记了它的外观array_agg()
。为了进行回顾,现代聚合是这样写的。
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
但是,从前,它是这样写的,
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
因此,我尝试了一些测试数据。
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
结果令人惊讶。#OldSchoolCool方法大大提高了速度:加快了25%。而且,在不使用ORDER的情况下对其进行简化显示出相同的慢度。
# EXPLAIN ANALYZE SELECT ARRAY(SELECT x FROM foobar);
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Result (cost=104425.28..104425.29 rows=1 width=0) (actual time=1665.948..1665.949 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Seq Scan on foobar (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.032..716.793 rows=10000000 loops=1)
Planning time: 0.068 ms
Execution time: 1671.482 ms
(5 rows)
test=# EXPLAIN ANALYZE SELECT array_agg(x) FROM foobar;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=119469.60..119469.61 rows=1 width=32) (actual time=2155.154..2155.154 rows=1 loops=1)
-> Seq Scan on foobar (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.031..717.831 rows=10000000 loops=1)
Planning time: 0.054 ms
Execution time: 2174.753 ms
(4 rows)
所以,这是怎么回事。为什么array_agg(一个内部函数)比计划者的SQL伏都教徒慢得多?
使用“ x86_64-pc-linux-gnu上的PostgreSQL 9.5.5,由gcc(Ubuntu 6.2.0-5ubuntu12)6.2.0 20161005,64位编译”
array_agg()
或类似聚合函数的查询仍然可以通过子查询来利用索引,例如:SELECT ARRAY_AGG(c) FROM (SELECT c FROM t ORDER BY id) sub
。per-aggregateORDER BY
子句在您的示例中排除了索引的使用。数组构造函数比任何一个都可以使用相同的索引(或两者都不使用)时要快array_agg()
。它只是没有那么多用途。请参阅:dba.stackexchange.com/a/213724/3684