Postgresql
為什麼 array_agg() 比非聚合 ARRAY() 建構子慢?
我只是在回顧一些為pre-8.4 PostgreSQL編寫的舊程式碼,我看到了一些非常漂亮的東西。我記得以前有一個自定義函式可以做一些這樣的事情,但我忘記了 pre- 是什麼
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 voodoo 慢得多?
在 x86_64-pc-linux-gnu 上使用“ PostgreSQL 9.5.5,由 gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005, 64 位編譯”
關於ARRAY 建構子,沒有什麼“老派”或“過時”的(就是這樣
ARRAY(SELECT x FROM foobar)
)。它一如既往的現代。將它用於簡單的數組聚合。也可以從子查詢的結果構造一個數組。在這種形式中,數組建構子是用關鍵字
ARRAY
後跟括號(非括號)子查詢編寫的。聚合函式
array_agg()
更通用,因為它可以集成到SELECT
具有更多列的列表中,可能在同一 中進行更多聚合SELECT
,並且可以使用 組成任意組GROUP BY
。雖然 ARRAY 建構子只能從SELECT
返回單個列中返回單個數組。我沒有研究原始碼,但顯然更通用的工具也更昂貴。
{}
一個顯著的區別:如果沒有行符合條件,ARRAY 建構子返回一個空數組 ( )。array_agg()
返回NULL
相同。