Stavo solo rivedendo un vecchio codice scritto per PostgreSQL pre-8.4 e ho visto qualcosa di veramente elegante. Ricordo di avere una funzione personalizzata per fare un po 'di tutto ciò nel corso della giornata, ma ho dimenticato come era pre array_agg(). Per la revisione, l'aggregazione moderna è scritta in questo modo.
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
Tuttavia, una volta, è stato scritto in questo modo,
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
Quindi, l'ho provato con alcuni dati di test ..
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
I risultati sono stati sorprendenti .. Il modo #OldSchoolCool è stato enormemente più veloce: uno speedup del 25%. Inoltre, semplificandolo senza l'ORDINE, ha mostrato la stessa lentezza.
# 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)
Quindi, cosa sta succedendo qui. Perché array_agg , una funzione interna è molto più lenta del voodoo SQL del planner?
Utilizzando " PostgreSQL 9.5.5 su x86_64-pc-linux-gnu, compilato da gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005, 64-bit"
array_aggdeve tenere traccia dell'ordine dei suoi input in cui ilARRAYcostruttore sembra fare qualcosa di approssimativamente equivalente a aUNIONcome espressione internamente. Se dovessi avventurarmi in un'ipotesi,array_aggprobabilmente richiederebbe più memoria. Non sono stato in grado di testare esaurientemente questo, ma su PostgreSQL 9.6 in esecuzione su Ubuntu 16.04 laARRAY()query con haORDER BYusato un'unione esterna ed è stata più lenta dellaarray_aggquery. Come hai detto, a meno di leggere il codice, la tua risposta è la migliore spiegazione che abbiamo.