Gibt es einen Grund, sich über die Spaltenreihenfolge in einer Tabelle Gedanken zu machen?

82

Ich weiß, dass Sie die Spaltenreihenfolge in MySQL mit FIRST und AFTER ändern können, aber warum sollten Sie sich die Mühe machen? Gibt es wirklich einen Grund, sich darum zu kümmern, in welcher Reihenfolge sich Ihre Spalten in der Tabelle befinden, da gute Abfragen beim Einfügen von Daten Spalten explizit benennen?

lynn
quelle

Antworten:

92

Die Spaltenreihenfolge hatte große Auswirkungen auf die Leistung einiger der von mir optimierten Datenbanken, die sich über SQL Server, Oracle und MySQL erstrecken. Dieser Beitrag hat gute Faustregeln :

  • Primärschlüsselspalten zuerst
  • Fremdschlüsselspalten weiter.
  • Häufig durchsuchte Spalten weiter
  • Häufig aktualisierte Spalten später
  • Nullable Spalten zuletzt.
  • Am wenigsten verwendete nullfähige Spalten nach häufiger verwendeten nullbaren Spalten

Ein Beispiel für Leistungsunterschiede ist eine Indexsuche. Das Datenbankmodul findet eine Zeile basierend auf einigen Bedingungen im Index und erhält eine Zeilenadresse zurück. Angenommen, Sie suchen nach SomeValue und es befindet sich in dieser Tabelle:

 SomeId int,
 SomeString varchar(100),
 SomeValue int

Die Engine muss raten, wo SomeValue startet, da SomeString eine unbekannte Länge hat. Wenn Sie jedoch die Reihenfolge ändern in:

 SomeId int,
 SomeValue int,
 SomeString varchar(100)

Jetzt weiß die Engine, dass SomeValue 4 Bytes nach dem Start der Zeile gefunden werden kann. Die Spaltenreihenfolge kann daher erhebliche Auswirkungen auf die Leistung haben.

BEARBEITEN: SQL Server 2005 speichert Felder mit fester Länge am Anfang der Zeile. Und jede Zeile hat einen Verweis auf den Beginn eines Varchars. Dies negiert den oben aufgeführten Effekt vollständig. Bei neueren Datenbanken hat die Spaltenreihenfolge keine Auswirkungen mehr.

Andomar
quelle
4
@ TopBanana: Nicht mit Varchars, das ist es, was sie von normalen Char-Spalten unterscheidet.
Allain Lalonde
1
Ich denke nicht, dass die Reihenfolge der Spalten in der Tabelle einen Unterschied macht - es macht definitiv einen Unterschied in den INDEXEN, die Sie möglicherweise erstellen.
marc_s
4
@ TopBanana: nicht sicher, ob Sie Oracle kennen oder nicht, aber es reserviert nicht 100 Bytes für eine VARCHAR2 (100)
Quassnoi
1
@Quassnoi: Die größte Auswirkung hatte SQL Server in einer Tabelle mit vielen nullbaren varchar () - Spalten.
Andomar
7
Die URL in dieser Antwort funktioniert nicht mehr. Hat jemand eine Alternative?
Scunliffe
41

Aktualisieren:

In MySQLkann es einen Grund dafür geben.

Da variable Datentypen (wie VARCHAR) mit variablen Längen in InnoDBgespeichert werden, sollte das Datenbankmodul alle vorherigen Spalten in jeder Zeile durchlaufen, um den Versatz der angegebenen zu ermitteln.

Die Auswirkung kann bei Spalten bis zu 17%20 betragen.

Siehe diesen Eintrag in meinem Blog für weitere Details:

In Oraclenachgestellten NULLSpalten wird kein Speicherplatz belegt. Deshalb sollten Sie sie immer an das Ende der Tabelle setzen.

Auch in Oracleund in SQL Server, im Falle einer großen Reihe, ROW CHAININGkann a auftreten.

ROW CHANING teilt eine Zeile, die nicht in einen Block passt, und verteilt sie auf mehrere Blöcke, die mit einer verknüpften Liste verbunden sind.

Das Lesen von nachfolgenden Spalten, die nicht in den ersten Block passen, erfordert das Durchlaufen der verknüpften Liste, was zu einer zusätzlichen I/OOperation führt.

Siehe diese Seite zur Veranschaulichung ROW CHAININGin Oracle:

Aus diesem Grund sollten Sie häufig verwendete Spalten an den Anfang der Tabelle und Spalten, die Sie nicht häufig verwenden, oder Spalten, die häufig verwendet werden NULL, an das Ende der Tabelle setzen.

Wichtige Notiz:

Wenn Ihnen diese Antwort gefällt und Sie dafür stimmen möchten, stimmen Sie bitte auch für @Andomardie Antwort ab .

Er antwortete auf das Gleiche, scheint aber ohne Grund abgelehnt zu werden.

Quassnoi
quelle
1
Sie sagen also, dies wäre langsam: Wählen Sie tinyTable.id, tblBIG.firstColumn, tblBIG.lastColumn aus tinyTable inner join tblBIG auf tinyTable.id = tblBIG.fkID aus, wenn tblBIG-Datensätze über 8 KB groß sind (in diesem Fall würde eine Zeilenverkettung auftreten ) und der Join wäre synchron ... Aber das wäre schnell: Wählen Sie tinyTable.id, tblBIG.firstColumn aus tinyTable inner join tblBIG auf tinyTable.id = tblBIG.fkID Da ich die Spalte nicht in anderen Blöcken verwenden würde, daher nein müssen die verknüpfte Liste durchqueren Habe ich das richtig verstanden?
jfrobishow
1
Ich bekomme nur 6%, und das ist für col1 im Vergleich zu jeder anderen Spalte.
Rick James
6

Während der Oracle-Schulung bei einem früheren Job schlug unser DBA vor, dass es vorteilhaft sei, alle nicht nullbaren Spalten vor die nullbaren zu setzen ... obwohl TBH ich mich nicht an die Details des Grundes erinnere. Oder waren es vielleicht nur diejenigen, die wahrscheinlich aktualisiert wurden, die am Ende gehen sollten? (Vielleicht muss die Zeile verschoben werden, wenn sie erweitert wird.)

Im Allgemeinen sollte es keinen Unterschied machen. Wie Sie sagen, sollten Abfragen immer Spalten selbst angeben, anstatt sich auf die Reihenfolge von "select *" zu verlassen. Ich kenne keine Datenbank, mit der sie geändert werden können ... nun, ich wusste nicht, dass MySQL dies zulässt, bis Sie es erwähnt haben.

araqnid
quelle
4
Er hatte Recht, Oracle schreibt keine nachgestellten NULL-Spalten auf die Festplatte und spart einige Bytes. Siehe dba-oracle.com/oracle_tips_ault_nulls_values.htm
Andomar
Absolut, es kann einen großen Unterschied in der Größe auf der Festplatte machen
Alex
Ist das der Link, den du gemeint hast? Es hängt eher mit der Nichtindizierung von Null in Indizes als mit der Spaltenreihenfolge zusammen.
Araqnid
Falscher Link und kann das Original nicht finden. Obwohl Sie dafür googeln können, zum Beispiel tlingua.com/new/articles/Chapter2.html
Andomar
5

Einige schlecht geschriebene Anwendungen hängen möglicherweise von der Spaltenreihenfolge / dem Spaltenindex anstelle des Spaltennamens ab. Sie sollten es nicht sein, aber es passiert. Das Ändern der Reihenfolge der Spalten würde solche Anwendungen beschädigen.

Craig Walker
quelle
2
Anwendungsentwickler, die ihren Code von der Spaltenreihenfolge in einer Tabelle abhängig machen, VERDIENEN, dass ihre Anwendungen beschädigt werden. Aber die Benutzer der Anwendung haben den Ausfall nicht verdient.
Spencer7593
5

Nein, die Reihenfolge der Spalten in einer SQL-Datenbanktabelle ist völlig irrelevant - außer für Anzeige- / Druckzwecke. Es macht keinen Sinn, Spalten neu anzuordnen - die meisten Systeme bieten nicht einmal eine Möglichkeit, dies zu tun (außer die alte Tabelle zu löschen und sie mit der neuen Spaltenreihenfolge neu zu erstellen).

Marc

BEARBEITEN: Aus dem Wikipedia-Eintrag in der relationalen Datenbank ist hier der relevante Teil, der mir klar zeigt, dass die Spaltenreihenfolge niemals von Belang sein sollte:

Eine Beziehung ist definiert als eine Menge von n-Tupeln. Sowohl in der Mathematik als auch im relationalen Datenbankmodell ist eine Menge eine ungeordnete Sammlung von Elementen, obwohl einige DBMS ihren Daten eine Reihenfolge auferlegen. In der Mathematik hat ein Tupel eine Reihenfolge und ermöglicht die Vervielfältigung. EF Codd definierte ursprünglich Tupel unter Verwendung dieser mathematischen Definition. Später war es eine der großartigen Erkenntnisse von EF Codd, dass die Verwendung von Attributnamen anstelle einer Reihenfolge in einer auf Beziehungen basierenden Computersprache (im Allgemeinen) viel praktischer wäre. Diese Erkenntnis wird noch heute genutzt.

marc_s
quelle
1
Ich habe gesehen, dass Spaltenunterschiede einen großen Einfluss auf meine eigenen Augen haben, daher kann ich nicht glauben, dass dies die richtige Antwort ist. Auch wenn die Abstimmung an erster Stelle steht. Hrm.
Andomar
In welcher SQL-Umgebung würde sich das befinden?
marc_s
1
Die größte Auswirkung, die ich gesehen habe, war auf SQL Server 2000, wo das Vorwärtsbewegen eines Fremdschlüssels einige Abfragen zwei- bis dreimal beschleunigte. Diese Abfragen hatten große Tabellenscans (1 Million + Zeilen) mit einer Bedingung für den Fremdschlüssel.
Andomar
5
RDBMS hängt nicht von der Tabellenreihenfolge ab, es sei denn, Sie legen Wert auf Leistung . Unterschiedliche Implementierungen haben unterschiedliche Leistungseinbußen für die Reihenfolge der Spalten. Es kann riesig oder winzig sein, es hängt von der Implementierung ab. Tupel sind theoretisch, RDBMS sind praktisch.
Esteban Küber
3
-1. Alle relationalen Datenbanken, die ich verwendet habe, haben auf einer bestimmten Ebene eine Spaltenreihenfolge. Wenn Sie * aus einer Tabelle auswählen, erhalten Sie die Spalten nicht in zufälliger Reihenfolge zurück. Jetzt ist On-Disk vs Display eine andere Debatte. Und das Zitieren der Mathematiktheorie, um eine Annahme über praktische Implementierungen von Datenbanken zu stützen, ist nur Unsinn.
DougW
4

Lesbarkeit der Ausgabe, wenn Sie Folgendes eingeben müssen:

select * from <table>

in Ihrer Datenbankverwaltungssoftware?

Es ist ein sehr falscher Grund, aber im Moment fällt mir nichts anderes ein.

ChrisF
quelle
2

Der einzige Grund, an den ich denken kann, ist das Debuggen und die Brandbekämpfung. Wir haben eine Tabelle, deren "Name" -Spalte ungefähr auf Platz 10 der Liste steht. Es ist schmerzhaft, wenn Sie eine schnelle Auswahl * aus der Tabelle mit der ID in (1,2,3) vornehmen und dann einen Bildlauf durchführen müssen, um die Namen anzuzeigen.

Aber das war es schon.

Chris Simpson
quelle
1

Wie so oft ist der größte Faktor der nächste, der am System arbeiten muss. Ich versuche, zuerst die Primärschlüsselspalten, dann die Fremdschlüsselspalten und dann den Rest der Spalten in absteigender Reihenfolge der Wichtigkeit / Bedeutung für das System zu haben.

James L.
quelle
Wir beginnen normalerweise mit der letzten Spalte, die "erstellt" wird (Zeitstempel für das Einfügen der Zeile). Bei älteren Tabellen können danach natürlich mehrere Spalten hinzugefügt werden ... Und es gibt gelegentlich Tabellen, in denen ein zusammengesetzter Primärschlüssel in einen Ersatzschlüssel geändert wurde, sodass der Primärschlüssel mehrere Spalten umfasst.
Araqnid
1

Wenn Sie UNION häufig verwenden, erleichtert dies das Abgleichen von Spalten, wenn Sie eine Konvention über deren Reihenfolge haben.

Allain Lalonde
quelle
Klingt so, als müsste Ihre Datenbank normalisiert werden! :)
James L
Hallo! Nimm es zurück, ich habe meine Datenbank nicht gesagt. :)
Allain Lalonde
Es gibt berechtigte Gründe, UNION zu verwenden;) Siehe postgresql.org/docs/current/static/ddl-partitioning.html und stackoverflow.com/questions/863867/…
Esteban Küber
Können Sie UNION mit der Reihenfolge der Spalten in 2 Tabellen in unterschiedlicher Reihenfolge?
Monica Heddneck
Ja, Sie müssen nur die Spalten explizit angeben, wenn Sie die Tabellen abfragen. Bei den Tabellen A [a, b] B [b, a] bedeutet dies (SELECT aa, ab FROM A) UNION (SELECT ba, bb FROM B) anstelle von (SELECT * FROM A) UNION (SELECT * FROM B).
Allain Lalonde
1

Wie bereits erwähnt, gibt es zahlreiche potenzielle Leistungsprobleme. Ich habe einmal an einer Datenbank gearbeitet, in der das Platzieren sehr großer Spalten am Ende die Leistung verbesserte, wenn Sie diese Spalten in Ihrer Abfrage nicht referenzierten. Wenn ein Datensatz mehrere Plattenblöcke umfasst, kann das Datenbankmodul anscheinend das Lesen von Blöcken beenden, sobald alle erforderlichen Spalten vorhanden sind.

Natürlich hängen die Auswirkungen auf die Leistung nicht nur stark vom Hersteller ab, den Sie verwenden, sondern möglicherweise auch von der Version. Vor einigen Monaten habe ich festgestellt, dass unsere Postgres keinen Index für einen "Gefällt mir" -Vergleich verwenden konnten. Das heißt, wenn Sie "eine Spalte wie 'M%'" geschrieben haben, war es nicht klug genug, zu den Ms zu springen und zu beenden, wenn das erste N gefunden wurde. Ich hatte vor, eine Reihe von Abfragen zu ändern, um "zwischen" zu verwenden. Dann haben wir eine neue Version von Postgres bekommen, die intelligent mit ähnlichen Dingen umgeht. Ich bin froh, dass ich nie dazu gekommen bin, die Abfragen zu ändern. Natürlich nicht direkt relevant, aber mein Punkt ist, dass alles, was Sie aus Effizienzgründen tun, mit der nächsten Version überholt sein könnte.

Die Spaltenreihenfolge ist für mich fast immer sehr relevant, da ich routinemäßig generischen Code schreibe, der das Datenbankschema liest, um Bildschirme zu erstellen. Meine Bildschirme zum Bearbeiten eines Datensatzes werden fast immer erstellt, indem ich das Schema lese, um die Liste der Felder abzurufen und sie dann der Reihe nach anzuzeigen. Wenn ich die Reihenfolge der Spalten ändern würde, würde mein Programm immer noch funktionieren, aber die Anzeige könnte für den Benutzer seltsam sein. Sie erwarten, dass Name / Adresse / Stadt / Bundesland / Postleitzahl angezeigt wird, nicht Stadt / Adresse / Postleitzahl / Name / Bundesland. Sicher, ich könnte die Anzeigereihenfolge der Spalten in Code oder eine Steuerdatei oder so etwas einfügen, aber jedes Mal, wenn wir eine Spalte hinzufügen oder entfernen, müssen wir daran denken, die Steuerdatei zu aktualisieren. Ich mag es, Dinge einmal zu sagen. Wenn der Bearbeitungsbildschirm nur aus dem Schema erstellt wird, Das Hinzufügen einer neuen Tabelle kann bedeuten, dass keine Codezeilen geschrieben werden, um einen Bearbeitungsbildschirm dafür zu erstellen, was sehr cool ist. (Nun, okay, in der Praxis muss ich normalerweise einen Eintrag zum Menü hinzufügen, um das generische Bearbeitungsprogramm aufzurufen, und ich habe generell auf das generische "Auswählen eines zu aktualisierenden Datensatzes" verzichtet, da es zu viele Ausnahmen gibt, um es praktisch zu machen .)

Jay
quelle
1

Abgesehen von der offensichtlichen Leistungsoptimierung stieß ich auf einen Eckfall, in dem das Neuordnen von Spalten dazu führte, dass ein (zuvor funktionsfähiges) SQL-Skript fehlschlug.

Aus der Dokumentation "TIMESTAMP- und DATETIME-Spalten haben keine automatischen Eigenschaften, es sei denn, sie werden explizit angegeben, mit dieser Ausnahme: Standardmäßig enthält die erste TIMESTAMP-Spalte sowohl DEFAULT CURRENT_TIMESTAMP als auch ON UPDATE CURRENT_TIMESTAMP, wenn keine explizit angegeben ist" https: //dev.mysql .com / doc / refman / 5.6 / de / timestamp-initialization.html

Ein Befehl ALTER TABLE table_name MODIFY field_name timestamp(6) NOT NULL;funktioniert also, wenn dieses Feld der erste Zeitstempel (oder Datum / Uhrzeit) in einer Tabelle ist, aber nicht anders.

Natürlich können Sie diesen Befehl alter so korrigieren, dass er einen Standardwert enthält, aber die Tatsache, dass eine Abfrage, die funktioniert hat, aufgrund einer Neuordnung der Spalten nicht mehr funktioniert, hat meinen Kopf verletzt.

slacker525600
quelle
0

Sie müssen sich nur dann um die Spaltenreihenfolge kümmern, wenn sich Ihre Software speziell auf diese Reihenfolge stützt. In der Regel ist dies auf die Tatsache zurückzuführen, dass der Entwickler faul geworden ist und a ausgeführt hat select *und dann in seinem Ergebnis nach Index und nicht nach Namen auf die Spalten verwiesen hat.

Soviut
quelle
0

Im Allgemeinen geschieht in SQL Server beim Ändern der Spaltenreihenfolge über Management Studio, dass eine temporäre Tabelle mit der neuen Struktur erstellt, die Daten aus der alten Tabelle in diese Struktur verschoben, die alte Tabelle gelöscht und die neue umbenannt werden. Wie Sie sich vorstellen können, ist dies eine sehr schlechte Wahl für die Leistung, wenn Sie einen großen Tisch haben. Ich weiß nicht, ob My SQL dasselbe tut, aber es ist ein Grund, warum viele von uns es vermeiden, Spalten neu zu ordnen. Da select * niemals in einem Produktionssystem verwendet werden sollte, ist das Hinzufügen von Spalten am Ende für ein gut gestaltetes System kein Problem. Die Reihenfolge der Spalten in der Tabelle sollte im Allgemeinen nicht beeinträchtigt werden.

HLGEM
quelle