Eu estava revisando algum código antigo escrito para o PostgreSQL anterior à 8.4 e vi algo realmente bacana. Lembro-me de ter uma função personalizada para fazer isso antes, mas esqueci como array_agg()
era. Para revisão, a agregação moderna é escrita assim.
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
No entanto, era uma vez, foi escrito assim,
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
Então, eu tentei com alguns dados de teste ..
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
Os resultados foram surpreendentes. A maneira #OldSchoolCool foi massivamente mais rápida: uma aceleração de 25%. Além disso, simplificá-lo sem a ORDEM, mostrou a mesma lentidão.
# 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)
Então, o que está acontecendo aqui. Por que array_agg , uma função interna é muito mais lenta que o vodu SQL do planejador?
Usando o " PostgreSQL 9.5.5 no x86_64-pc-linux-gnu, compilado pelo gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005, 64 bits"
array_agg
deve acompanhar a ordem de suas entradas em que oARRAY
construtor parece estar fazendo algo aproximadamente equivalente a aUNION
como uma expressão internamente. Se eu tivesse que arriscar um palpite,array_agg
provavelmente exigiria mais memória. Não pude testar exaustivamente isso, mas no PostgreSQL 9.6 executando no Ubuntu 16.04, aARRAY()
consultaORDER BY
usou uma mesclagem externa e foi mais lenta que aarray_agg
consulta. Como você disse, antes de ler o código, sua resposta é a melhor explicação que temos.