Estaba revisando un código antiguo escrito para PostgreSQL anterior a 8.4 , y vi algo realmente ingenioso. Recuerdo que una función personalizada hizo algo de esto en el día, pero olvidé cómo se array_agg()
veía previamente. Para su revisión, la agregación moderna se escribe así.
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
Sin embargo, una vez, se escribió así,
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
Entonces, lo probé con algunos datos de prueba ...
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
Los resultados fueron sorprendentes. La forma #OldSchoolCool fue enormemente más rápida: una aceleración del 25%. Además, al simplificarlo sin ORDEN, se mostró la misma lentitud.
# 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)
Entonces, ¿qué está pasando aquí? ¿Por qué es array_agg , una función interna mucho más lenta que el vudú SQL del planificador?
Usando " PostgreSQL 9.5.5 en x86_64-pc-linux-gnu, compilado por gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005, 64 bits"
array_agg
debe realizar un seguimiento del orden de sus entradas donde elARRAY
constructor parece estar haciendo algo aproximadamente equivalente a aUNION
como una expresión interna. Si tuviera que aventurarme a adivinar,array_agg
probablemente requeriría más memoria. No pude probar exhaustivamente esto, pero en PostgreSQL 9.6 que se ejecuta en Ubuntu 16.04 laARRAY()
consultaORDER BY
utilizó una fusión externa y fue más lenta que laarray_agg
consulta. Como dijiste, antes de leer el código, tu respuesta es la mejor explicación que tenemos.