Warum ist SELECT * viel schneller als das Auswählen aller Spalten (in einer anderen Spaltenreihenfolge) nach Namen?


12

Auf einer Tabelle mit den Spalten a, b, c, d, e, f, g, h, i, j, k erhalte ich:

select * from misty order by a limit 25;
Time: 302.068 ms

Und:

select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;
Time: 1258.451 ms

Gibt es eine Möglichkeit, die Auswahl nach Spalte so schnell wie möglich vorzunehmen?

Aktualisieren:

Kein Index für eine Tabelle, neu erstellt

Hier ist die EXPLAIN ANALYZE, die nicht allzu hilfreich zu sein scheint:

explain analyze select * from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=404.958..404.971 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=404.957..404.963 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.013..170.945 rows=694686 loops=1)
Total runtime: 405.019 ms
(6 rows)

Und:

explain analyze select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=1371.735..1371.745 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=1371.733..1371.736 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.015..516.355 rows=694686 loops=1)
Total runtime: 1371.797 ms
(6 rows)

Ist die Spalte indiziert? Kannst du das erklären analysieren?
user_0

1
Sie müssen vorsichtig sein, zwei Auswahlen hintereinander zu treffen und die Zeiten zu vergleichen. Die Daten im Cache der zweiten Abfrage können den Zeitunterschied ausmachen.
Walter Mitty

1
Ich sehe auch Unterschiede, wenn auch nicht so ausgeprägt. Meine Tabelle hat Zeilen = 514431 Breite = 215, und ich erhalte ca. 1,5 s für den select *Fall und ca. 2,2 s für die Auswahl mit Spalten, die in einer anderen Reihenfolge aufgeführt sind .
Colin 't Hart

Wenn ich alle Spalten in derselben Reihenfolge aufführe, wie sie in der Tabelle definiert sind, erhalte ich ungefähr die gleichen Zeiten wie ich select *.
Colin 't Hart

2
Der Titel ist irreführend. Die Frage ist wirklich, warum die Dauer einer Sortierung von der Reihenfolge der Ausgabespalten abhängt.
Daniel Vérité

Antworten:


12

Dies wurde auf der Mailingliste von pgsql-hackers gepostet und ich habe versucht, dort kurz zu antworten. Wenn die Zielliste (angegebene Spalten) genau mit dem Tupeldeskriptor der Beziehung übereinstimmt, dh sowohl in Anzahl der Spalten als auch in der Reihenfolge, kann der zugrunde liegende Scan ein Tupel zurückgeben, das direkt vom einschließenden Sortierknoten verarbeitet werden kann. Wenn andererseits die Zielliste nicht übereinstimmt (entweder in der Reihenfolge oder in der Anzahl der angegebenen Spalten), gibt der Scan eine Form der Tupel zurück, für die der Datenvorbereitungsschritt von Sort zusätzliche Arbeit erfordert (von einem internen Tupelformat in konvertieren) das vom Sortiercode direkt konsumierbare Format).

Übrigens wird '*' intern in eine Liste umgewandelt, die (intuitiv) mit dem Tupeldeskriptor der Relation übereinstimmt.

BEARBEITEN: Wenn Sie sich die tatsächlichen Zeiten Ihres letzten EXPLAIN ANALYZE-Seq-Scans ansehen, können Sie sehen, dass es mehr als die früheren sind. Dies geschah, weil der Scan einen zusätzlichen Projektionsschritt ausführte (dh das Konvertieren des Heap-Tupels in ein Format für interne Werte [], Nullen []). Und da dies geschah, musste der obere Sortierknoten zusätzliche Arbeit bei der Dateninitialisierung leisten, nämlich die Konvertierung in das Tupelformat, das der eigentliche Sortierschritt versteht. Das geht aus den Startkosten der Sort hervor. Das passiert im ersteren Fall nicht. Das heißt, der Scan gibt das Tupel so zurück, wie es ist, und der Initialisierungsschritt der Sortierung kopiert es einfach.


@ Colin'tHart, hoffe das macht Sinn.
Amitlan

Ja. Ich hätte gehofft, dass es möglich wäre, diesen Schritt zu überspringen oder ihn mit etwas "Zeigermischen" zu verkürzen, aber das ist eine Diskussion für Pgsql-Hacker.
Colin 't Hart

Mit der kürzlichen Wiederbelebung der Arbeit zur logischen Spaltenreihenfolge können sich einige Verbesserungen abzeichnen.
Amitlan

Ich habe schon darüber nachgedacht und es gehofft!
Colin 't Hart

Sehr geehrter Herr, wenn ich statt aller nur einige Spalten brauche, welche werden schneller sein? select * oder select some_of_columns? Danke vielmals.
sgon00
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.