Ziemlich einfache Frage, wahrscheinlich irgendwo beantwortet, aber ich kann scheinbar nicht die richtige Suchfrage für Google bilden ...
Beeinflusst die Anzahl der Spalten in einer bestimmten Tabelle die Leistung einer Abfrage, wenn eine Teilmenge dieser Tabelle abgefragt wird?
Wenn beispielsweise die Tabelle Foo 20 Spalten enthält, meine Abfrage jedoch nur 5 dieser Spalten auswählt, wirken sich dann 20 Spalten (gegenüber beispielsweise 10 Spalten) auf die Abfrageleistung aus? Der Einfachheit halber sei angenommen, dass irgendetwas in der WHERE-Klausel in diesen 5 Spalten enthalten ist.
Ich mache mir Sorgen über die Verwendung des Puffercaches von Postgres zusätzlich zum Festplattencache des Betriebssystems. Ich habe ein sehr schlechtes Verständnis für das physische Speicherdesign von Postgres. Tabellen werden auf mehreren Seiten gespeichert (standardmäßig 8 KB pro Seite), aber ich verstehe nicht ganz, wie Tupel von dort angeordnet sind. Ist PG intelligent genug, um nur die Daten von der Festplatte abzurufen, die diese 5 Spalten umfassen?
quelle
Antworten:
Der physische Speicher für Zeilen ist in den Dokumenten unter Datenbankseitenlayout beschrieben . Der Spalteninhalt für dieselbe Zeile wird alle auf derselben Datenträgerseite gespeichert, mit Ausnahme des Inhalts von TOAST (zu groß, um auf eine Seite zu passen). Der Inhalt wird nacheinander in jeder Zeile extrahiert, wie nachfolgend erläutert:
Im einfachsten Fall (keine TOAST-Spalten) ruft postgres die gesamte Zeile ab, auch wenn nur wenige Spalten benötigt werden. In diesem Fall lautet die Antwort also "Ja". Wenn mehr Spalten vorhanden sind, kann sich dies eindeutig nachteilig auf den Puffercache auswirken, insbesondere wenn der Spalteninhalt groß ist und sich noch unter dem TOAST-Schwellenwert befindet.
Nun der TOAST-Fall: Wenn ein einzelnes Feld ~ 2 KB überschreitet, speichert die Engine den Feldinhalt in einer separaten physischen Tabelle. Es kommt auch ins Spiel, wenn die gesamte Zeile nicht auf eine Seite passt (standardmäßig 8 KB): Einige der Felder werden in den TOAST-Speicher verschoben. Doc sagt:
TOAST'ed-Inhalte werden nicht abgerufen, wenn sie nicht ausdrücklich benötigt werden. Daher ist ihre Auswirkung auf die Gesamtzahl der abzurufenden Seiten gering (einige Bytes pro Spalte). Dies erklärt die Ergebnisse in der Antwort von @ dezso.
Wie beim Schreiben wird jede Zeile mit all ihren Spalten bei jedem UPDATE vollständig neu geschrieben, unabhängig davon, welche Spalten geändert werden. Wenn Sie also mehr Spalten haben, ist dies für Schreibvorgänge offensichtlich teurer.
quelle
Daniels Antwort konzentriert sich auf die Kosten für das Lesen einzelner Zeilen. In diesem Zusammenhang
NOT NULL
hilft es ein wenig, Spalten mit fester Größe an erster Stelle in Ihre Tabelle zu setzen. Es hilft ein wenig, die relevanten Spalten (die, nach denen Sie fragen) an erster Stelle zu setzen. Das Minimieren des Auffüllens (aufgrund der Datenausrichtung) durch Spielen von Ausrichtungstetris mit Ihren Spalten kann ein wenig helfen. Der wichtigste Effekt wurde jedoch noch nicht erwähnt, insbesondere bei großen Tischen.Zusätzliche Spalten sorgen offensichtlich dafür, dass eine Zeile mehr Speicherplatz abdeckt, sodass weniger Zeilen auf eine Datenseite passen (standardmäßig 8 KB). Einzelne Zeilen sind auf mehrere Seiten verteilt. Das Datenbankmodul muss im Allgemeinen ganze Seiten abrufen, nicht einzelne Zeilen . Es spielt keine Rolle, ob einzelne Zeilen etwas kleiner oder größer sind - solange die gleiche Anzahl von Seiten gelesen werden muss.
Wenn eine Abfrage einen (relativ) kleinen Teil einer großen Tabelle abruft, bei dem die Zeilen mehr oder weniger zufällig über die gesamte Tabelle verteilt sind, was durch einen Index unterstützt wird, führt dies zu ungefähr der gleichen Anzahl von Seitenlesevorgängen, ohne dass dies berücksichtigt wird zu Zeilengröße. Irrelevante Spalten verlangsamen Sie in einem solchen (seltenen) Fall nicht sehr.
In der Regel rufen Sie Patches oder Cluster von Zeilen ab, die nacheinander oder in der Nähe eingegeben wurden, und geben Datenseiten frei. Diese Zeilen sind aufgrund der Unordnung verteilt. Es müssen mehr Plattenseiten gelesen werden, um Ihre Abfrage zu erfüllen. Das Lesen weiterer Seiten ist in der Regel der wichtigste Grund für eine langsamere Abfrage. Und das ist der wichtigste Faktor, warum irrelevante Spalten Ihre Abfragen langsamer machen.
Bei großen Datenbanken ist in der Regel nicht genügend RAM vorhanden, um den gesamten Arbeitsspeicher im Cache zu halten. Größere Zeilen belegen mehr Cache, mehr Konflikte, weniger Cache-Treffer und mehr Festplatten-E / A. Und Festplattenlesevorgänge sind in der Regel viel teurer. Weniger bei SSDs, aber ein wesentlicher Unterschied bleibt. Dies fügt dem obigen Punkt über Seitenlesevorgänge hinzu.
Es kann von Bedeutung sein, ob irrelevante Spalten TOAST-ed sind. Relevante Spalten können auch TOAST-ed sein, wodurch der gleiche Effekt erzielt wird.
quelle
Ein kleiner Test:
Das Begrenzen der Abfrage auf die ersten 250 Zeilen (
WHERE num <= 250
) führt zu 34.539 ms bzw. 8.343 ms. Die Auswahl aller außerlong_long_text
dieser begrenzten Menge führt zu 18.432 ms. Dies zeigt, dass PG in Ihren Begriffen klug genug ist.quelle