Wie wirken sich vollständig leere Spalten in einer großen Tabelle auf die Leistung aus?


8

Ich habe 400 Millionen Zeilen in einer Postgres-Datenbank und die Tabelle enthält 18 Spalten:

id serial NOT NULL,
a integer,
b integer,
c integer,
d smallint,
e timestamp without time zone,
f smallint,
g timestamp without time zone,
h integer,
i timestamp without time zone,
j integer,
k character varying(32),
l integer,
m smallint,
n smallint,
o character varying(36),
p character varying(100),
q character varying(100)

Spalten e, kund nsind alle NULL, sie speichern überhaupt keine Werte und sind zu diesem Zeitpunkt völlig nutzlos. Sie waren Teil des ursprünglichen Entwurfs, wurden jedoch nie entfernt.

Bearbeiten - Die meisten anderen Spalten sind nicht NULL.

Fragen:

  1. Wie kann ich die Auswirkungen auf die Lagerung berechnen? Entspricht es der Größe der Spalte * Anzahl der Zeilen?

  2. Wird das Löschen dieser leeren Spalten die Leistung dieser Tabelle spürbar verbessern? Würde der Seitencache mehr Zeilen aufnehmen können?

Antworten:


12

Da die Spalten e, kund nNULL sein kann, gehe ich davon aus Mitteln NULL „100% leer“.

NULL Speicher ist billig. Jeder NULL "kostet" ein Bit in der Null-Bitmap für die Speicherung und beeinträchtigt ansonsten kaum die Leistung. Die effektive Speicheranforderung hängt davon ab, ob für jede Zeile bereits eine Null-Bitmap vorhanden ist und Platz für 3 weitere Bits ist.

Tabellen mit bis zu 8 Spalten können ein Ersatzbyte nach dem Tupelheader für die Null-Bitmap verwenden. Danach werden weitere MAXALIGN(normalerweise 8) Bytes zugewiesen, die weitere 64 Spalten bereitstellen (insgesamt jetzt 72 ). Die Null-Bitmap kostet also für die meisten Tabellen effektiv 8 Bytes pro Zeile, einschließlich Ihrer mit 18 Spalten.

Die Null-Bitmap wird vollständig oder gar nicht pro Zeile zugewiesen und nur dann, wenn mindestens ein tatsächlicher NULL-Wert vorhanden ist . Wenn alle Spalten definiert sind NOT NULL, kann es niemals eine geben.

Wenn keine anderen, wichtigeren Überlegungen vorliegen, verschieben Sie Spalten, die immer (oder meistens) NULL sind, an das Ende der Zeile. Hilft die Leistung ein wenig.

Antwort auf 1.

Die effektive Speicheranforderung ist:

  • 0 Bytes pro Zeile, wobei andere Spalten ebenfalls NULL sind.
  • 8 Bytes (normalerweise) pro Zeile, in der keine andere Spalte NULL ist, zum Zuweisen der Null-Bitmap

Antwort auf 2.

Fallenlassen würde dir nicht viel kaufen. Der Seiten-Cache wäre abhängig von 1 gleich oder etwas kleiner. Die Bearbeitung von Abfragen, Sicherungen, Quellcode und dergleichen würde vereinfacht.

Mehr Informationen:

Was du nicht gefragt hast

Nach einer Runde "Column Tetris" würde ich dieses Tabellenlayout vorschlagen - abgesehen von anderen, wichtigeren Überlegungen:

id serial NOT NULL,
a integer,
b integer,
c integer,
g timestamp,
i timestamp,
d smallint,
f smallint,
h integer,
j integer,
l integer,
m smallint,
o character varying(36),
p character varying(100),
q character varying(100),
e timestamp,              --  always NULL
k character varying(32),  --  always NULL
n smallint                --  always NULL

Spart mindestens 16 Bytes pro Zeile im Vergleich zu Ihrem ursprünglichen Layout, wahrscheinlich mehr als 20 Byte, abhängig von Ihren varcharSpalten. Anleitung für "column tetris" hier:

So ordnen Sie Spalten neu an

Die einfachste Methode besteht darin, eine neue Tabelle zu erstellen und Daten in diese zu kopieren. Dann erhalten Sie eine makellose neue Tabelle ohne tote Spalten (und tote Zeilen). Sie können dabei auch die physische Reihenfolge der Zeilen sortieren (gruppieren).

Änderungen an Ort und Stelle sind ebenfalls möglich, aber es gibt kein praktisches Werkzeug (das ich kennen würde), um die Reihenfolge der Spalten generell neu zu ordnen. Abhängige Objekte wie Ansichten, Funktionen (abhängig), FK-Einschränkungen, Indizes usw. sind hier ein begrenzender Faktor. Diese können Sie daran hindern, eine Spalte zu löschen. Sie müssen abhängige Objekte löschen und neu erstellen.

Und natürlich steht der gleichzeitige Zugriff auf die Tabelle in Konflikt mit DDL-Befehlen, die diese ändern. In diesem Fall benötigen Sie exklusive Sperren.

Es ist einfach und kostengünstig, vollständig leere Spalten zu löschen und am Ende der Zeile hinzuzufügen. Das Umschalten der Reihenfolge der ausgefüllten Spalten in der Mitte der Tabelle ist nicht so einfach. Ich würde dafür eine neue Tabelle erstellen.

Diese verwandte Antwort enthält Rezepte und Links zu mehr:


Ist es möglich, das Tabellenlayout für eine vorhandene Tabelle anzupassen, oder müssten Sie die neue Tabelle erstellen und Daten von der alten migrieren?
ebi

@ebi: Ich habe einen Absatz dafür hinzugefügt.
Erwin Brandstetter
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.