Ich habe gerade einen alten Code überprüft, der für PostgreSQL vor 8.4 geschrieben wurde , und ich habe etwas wirklich Gutes gesehen. Ich erinnere mich, dass früher eine benutzerdefinierte Funktion etwas davon erledigte, aber ich vergaß, wie es vorher array_agg()
ausgesehen hatte. Zur Überprüfung wird die moderne Aggregation folgendermaßen geschrieben.
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
Es war jedoch einmal so geschrieben:
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
Also habe ich es mit ein paar Testdaten versucht ..
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
Die Ergebnisse waren überraschend. Die #OldSchoolCool-Methode war enorm schneller: eine 25% ige Beschleunigung. Darüber hinaus zeigte die Vereinfachung ohne die BESTELLUNG die gleiche Langsamkeit.
# 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)
Also, was ist hier los? Warum ist array_agg , eine interne Funktion, so viel langsamer als der SQL-Voodoo des Planers?
Verwenden von " PostgreSQL 9.5.5 unter x86_64-pc-linux-gnu, kompiliert von gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005, 64-bit"
array_agg
muss die Reihenfolge seiner Eingaben verfolgen, in der derARRAY
KonstruktorUNION
intern etwas zu tun scheint, das ungefähr dem Ausdruck a entspricht. Wenn ich eine Vermutung wagenarray_agg
müsste , würde wahrscheinlich mehr Speicher benötigt. Ich konnte dies nicht ausführlich testen, aber auf PostgreSQL 9.6 unter Ubuntu 16.04 verwendete dieARRAY()
AbfrageORDER BY
eine externe Zusammenführung und war langsamer als diearray_agg
Abfrage. Wie Sie sagten, ist Ihre Antwort nach dem Lesen des Codes die beste Erklärung, die wir haben.