Manchmal entsteht die Aufgabe, eine integrale Auswahl mit denselben Daten "in Spalten" aus den linearen Arrays, die als Parameter an die SQL-Abfrage übergeben wurden, zu "kleben".
Wie wird es manchmal gemacht:
WITH T1 AS ( SELECT row_number() OVER() rn , unnest v1 FROM unnest('{1,2,3,4}'::integer[]) ) , T2 AS ( SELECT row_number() OVER() rn , unnest v2 FROM unnest('{5,6}'::integer[]) ) SELECT T1.v1 , T2.v2 FROM T1 LEFT JOIN T2 USING(rn);
v1 | v2 ------- 1 | 5 2 | 6 3 | 4 |
Das heißt, zunächst wurde jedes der Arrays in das Sample „expandiert“, nummeriert und dann als CTE-Verbindungsschlüssel verwendet ...
[siehe EXPLAIN.TENSOR.RU]MIT ORDINALITÄT
Mehr als ein Viertel der Zeit wurde für ein paar WindowAgg!
Wenn wir jedoch eine Version von PG verwenden, die nicht niedriger als 9.4 ist,
können wir WITH ORDINALITY verwenden, um die Ergebnisse einer SRF zu nummerieren, einschließlich unnest:
WITH T1 AS ( SELECT * FROM unnest('{1,2,3,4}'::integer[]) WITH ORDINALITY T(v1, rn) ) , T2 AS ( SELECT * FROM unnest('{5,6}'::integer[]) WITH ORDINALITY T(v2, rn) ) SELECT T1.v1 , T2.v2 FROM T1 LEFT JOIN T2 USING(rn);
[siehe EXPLAIN.TENSOR.RU] .
Damit haben wir die Verwendung von Fensterfunktionen komplett überflüssig gemacht.
Mehrargument UNNEST
Aber aus Sicht der Effizienz ist noch nicht alles gut - fast die Hälfte der Zeit ging an Hash Left Join.
Und der Autor ging eindeutig davon aus, dass das erste Array genau länger ist - deshalb verwendete er LEFT JOIN. Diese Annahme ist jedoch nicht immer richtig und kann Probleme verursachen.
Um das zu
umgehen , werden wir
unnest für mehrere Arrays gleichzeitig verwenden , die ab derselben Version 9.4 erschienen sind:
SELECT * FROM unnest( '{1,2,3,4}'::integer[] , '{5,6}'::integer[] ) T(v1, v2);
Infolgedessen blieb fast nichts von der Bitte und dem Plan übrig:
Function Scan on t (cost=0.01..1.00 rows=100 width=8) (actual time=0.006..0.007 rows=4 loops=1)
Daher sind die Chancen, einen Fehler zu machen, viel geringer. Ja, und die Ausführungszeit wurde mehrmals verbessert - und bei längeren Arrays wird der Effekt noch deutlicher.