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"
fuente
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.array_agg()
es más rápido que el constructor de matrices? Por un caso simple? Muy improbable, pero si es así, probablemente porque Postgres basó su decisión para un plan de consulta en estadísticas inexactas de la configuración de costos. Nunca he vistoarray_agg()
superar a un constructor de matrices y lo he probado muchas veces.VACUUM ANALYZE
antes de ejecutar las consultas? Considere: dba.stackexchange.com/a/18694/3684