Ist die Reihenfolge der Spalten in der Definition einer Tabelle wichtig?


35

Beim Definieren einer Tabelle ist es hilfreich, die Spalten in logischen Gruppen und die Gruppen selbst nach Zweck zu ordnen. Die logische Anordnung der Spalten in einer Tabelle vermittelt dem Entwickler eine Bedeutung und ist ein Element guten Stils.

Das ist klar.

Es ist jedoch nicht klar, ob sich die logische Reihenfolge der Spalten in einer Tabelle auf ihre physische Reihenfolge auf der Speicherebene auswirkt oder ob sich dies auf andere Aspekte auswirkt, die für Sie von Belang sind.

Ist die Spaltenreihenfolge, abgesehen von den Auswirkungen auf den Stil, jemals von Bedeutung?

Zu diesem Thema gibt es eine Frage zum Stapelüberlauf , die jedoch nicht verbindlich beantwortet werden kann.

Antworten:


23

Hat die logische Reihenfolge der Spalten in einer Tabelle Auswirkungen auf ihre physische Reihenfolge auf der Speicherebene? Ja.

Ob es darauf ankommt oder nicht, ist ein anderes Thema, das ich (noch) nicht beantworten kann.

Schauen wir uns eine einfache zweispaltige Tabelle mit DBCC IND an, ähnlich wie in dem häufig verlinkten Artikel von Paul Randal über die Anatomie eines Datensatzes beschrieben:

SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;

USE master;
GO

IF DATABASEPROPERTY (N'RowStructure', 'Version') > 0 DROP DATABASE RowStructure;
GO

CREATE DATABASE RowStructure;
GO

USE RowStructure;
GO

CREATE TABLE FixedLengthOrder
(
    c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , c2 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL
    , c3 CHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL  
);
GO

INSERT FixedLengthOrder DEFAULT VALUES;
GO

DBCC IND ('RowStructure', 'FixedLengthOrder', 1);
GO

DBCC IND Ausgang

Die Ausgabe oben zeigt, dass wir uns Seite 89 ansehen müssen:

DBCC TRACEON (3604);
GO
DBCC PAGE ('RowStructure', 1, 89, 3);
GO

In der Ausgabe von DBCC PAGE sehen wir c1 gefüllt mit dem Zeichen 'A' vor c2 'B':

Memory Dump @0x000000000D25A060

0000000000000000:   10001c00 01000000 41414141 41414141 †........AAAAAAAA
0000000000000010:   41414242 42424242 42424242 030000††††AABBBBBBBBBB...

Und nur weil, lassen Sie RowStructure.mdfuns mit einem Hex-Editor aufspringen und bestätigen, dass die 'A'-Zeichenfolge der' B'-Zeichenfolge vorausgeht:

AAAAAAAAAA

Wiederholen Sie nun den Test, aber kehren Sie die Reihenfolge der Zeichenfolgen um, indem Sie die Zeichen 'B' in c1 und die Zeichen 'A' in c2 einfügen:

CREATE TABLE FixedLengthOrder
(
    c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , c2 CHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL
    , c3 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL  
);
GO

Diesmal ist unsere DBCC PAGE-Ausgabe anders und die 'B'-Zeichenfolge erscheint zuerst:

Memory Dump @0x000000000FC2A060

0000000000000000:   10001c00 01000000 42424242 42424242 †........BBBBBBBB 
0000000000000010:   42424141 41414141 41414141 030000††††BBAAAAAAAAAA... 

Lassen Sie uns noch einmal, nur um zu kichern, den Hex-Dump der Datendatei überprüfen:

BBBBBBBBBB

Wie Anatomy of a Record erläutert, werden die Spalten mit fester und variabler Länge eines Datensatzes in unterschiedlichen Blöcken gespeichert. Das logische Verschachteln von festen und variablen Spaltentypen hat keine Auswirkung auf den physischen Datensatz. Innerhalb jedes Blocks entspricht die Reihenfolge Ihrer Spalten jedoch der Reihenfolge der Bytes in der Datendatei.

CREATE TABLE FixedAndVariableColumns
(
    c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , c2 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL
    , c3 VARCHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL  
    , c4 CHAR(10) DEFAULT REPLICATE('C', 10) NOT NULL
    , c5 VARCHAR(10) DEFAULT REPLICATE('D', 10) NOT NULL
    , c6 CHAR(10) DEFAULT REPLICATE('E', 10) NOT NULL  
);
GO

Memory Dump @0x000000000E07C060

0000000000000000:   30002600 01000000 41414141 41414141 0.&.....AAAAAAAA 
0000000000000010:   41414343 43434343 43434343 45454545 AACCCCCCCCCCEEEE 
0000000000000020:   45454545 45450600 00020039 00430042 EEEEEE.....9.C.B 
0000000000000030:   42424242 42424242 42444444 44444444 BBBBBBBBBDDDDDDD 
0000000000000040:   444444†††††††††††††††††††††††††††††††DDD

Siehe auch:

Spaltenreihenfolge spielt keine Rolle ... im Allgemeinen, aber - ES HÄNGT AB!


+1 Ich stimme zu. Ich habe immer festgestellt, dass in jedem Abschnitt die Reihenfolge der Spalten anfangs der CREATE TABLEAnweisung entspricht (mit der Ausnahme, dass CI-Schlüsselspalten im Abschnitt an erster Stelle stehen). Die Reihenfolge der Spalten kann sich jedoch ändern, wenn ALTER COLUMNsich Datentypen / Spaltenlängen ändern . Der einzige kleine Fall , in dem es wichtig ist, dass ich mich vorstellen kann ist , dass Spalten am Ende des Abschnitts mit variabler Länge mit leeren String oder NULL überhaupt in der Spalte Offset - Array keinen Platz nehmen (nachgewiesen durch Kalen Delaney in den 2008 Interna buchen)
Martin Smith

1
Spaltenreihenfolge kann in seltenen Fällen von Bedeutung sein. Wenn Sie beispielsweise eine Tabelle mit 3 Spalten A, B und C haben, sind diese jeweils 3 KB lang. SQL Server-Seiten haben eine Größe von 8 KB, Cpassen also nicht und werden auf eine eigene erweiterte Seite verschoben . Also select A, Bvon YourTable` erfordert nur die halbe Seite liest aus select A, C from YourTable.
Andomar

"Whether it matters or not is a different issue that I can't answer (yet).": Die Reihenfolge der Spalten kann die Leistung erheblich beeinträchtigen. Außerdem kann es sogar zu Fehlern kommen! Überprüfen Sie dies - Demo 2 zeigt es besser, denke ich
Ronen Ariely

@RonenAriely Interessantes Beispiel, aber es ist im Kontext der ursprünglichen Frage etwas erfunden. Sie demonstrieren, wie sich die Spaltenreihenfolge auswirkt, wenn Sie die Spalte anschließend löschen. Ich glaube nicht, dass ich jemals einen Tisch mit Voraussicht entworfen habe, welche Spalten ich ablegen werde.
Mark Storey-Smith

Hi @ MarkStorey-Smith. (1) Als Architekt erkläre ich immer, dass der Unterschied zwischen Well Design und Great Design darin besteht, dass gutes Design die gegenwärtigen Bedürfnisse befriedigt, während Great Design die zukünftigen Bedürfnisse befriedigt, die noch nicht bekannt sind. (2) Die Antwort auf die Frage lautet JA. Die Umsetzung der Antwort obliegt dem OP und jedem von uns. Dies liegt außerhalb des Diskussionsbereichs, wir können dieses Thema jedoch zur Diskussion stellen. Aber nicht bei stackoverflow forums family, da die Schnittstelle keine echte Diskussion zulässt, sondern nur eine einzige schlechte kurze Textzeile in die Antworten
einfügt

7

Wenn Sie keinen Clustered-Index definieren, erhalten Sie eine Heap-Tabelle. Bei einer Heap-Tabelle wird beim Lesen von Daten immer gescannt, und daher werden die gesamten Zeilen gelesen, sodass die Reihenfolge der Spalten ein Diskussionspunkt ist.

Sobald Sie einen Clustered-Index definieren, werden die Daten physisch so neu angeordnet, dass sie der physischen Reihenfolge der von Ihnen angegebenen Spalten entsprechen - und an dieser Stelle wird die physische Reihenfolge wichtig. Die physische Reihenfolge bestimmt die Berechtigung des suchenden Operators basierend auf den Prädikaten, die Sie verwenden.

Obwohl ich mich nicht erinnern kann, es irgendwo gelesen zu haben, würde ich annehmen, dass SQL Server die physische Reihenfolge der Spalten für Heaps nicht garantiert, wohingegen dies für Indizes garantiert wird. Nein, um Ihre Frage zu beantworten, sollte die Reihenfolge der Spalten in der Definition keine Rolle spielen, da sie beim Lesen der Daten keine Rolle spielen (beachten Sie, dass dies nur für Heaps gilt - Indizes sind eine andere Sache).

Update
Tatsächlich stellen Sie zwei Fragen: "Ob sich die logische Reihenfolge der Spalten in einer Tabelle auf ihre physische Reihenfolge auf der Speicherebene auswirkt" ist eine Nr. Die durch die Metadaten definierte logische Reihenfolge muss nicht mit der physischen Reihenfolge übereinstimmen. Sie suchen nach einer Antwort darauf, ob die logische Reihenfolge in CREATE TABLE bei der Erstellung dieselbe physische Reihenfolge ergibt, die ich nicht kenne, für Haufen - allerdings mit der obigen Einschränkung.


2

Basierend auf dem, was ich gesehen und gelesen habe, macht die Reihenfolge der Spalten in SQL Server keinen Unterschied. Das Speichermodul platziert Spalten in der Zeile, unabhängig davon, wie sie in der Anweisung CREATE TABLE angegeben sind. Abgesehen davon bin ich sicher, dass es einige sehr isolierte Randfälle gibt, in denen es wichtig ist, aber ich denke, Sie werden es schwer haben, eine einzige endgültige Antwort auf diese Fragen zu bekommen. Paul Randals " Inside The Storage Engine"Die Blogkategorie von Posts ist die beste Quelle für alle mir bekannten Details zur Funktionsweise der Speicher-Engine. Ich denke, Sie müssten die verschiedenen Funktionsweisen des Speichers untersuchen und diese gegen alle Anwendungsfälle aufteilen Um die Kantenfälle zu finden, bei denen die Reihenfolge eine Rolle spielt. Wenn nicht ein spezifischer Kantenfall angegeben wird, der für meine Situation gilt, ordne ich die Spalten einfach logisch auf meiner CREATE TABLE an. Ich hoffe, dies hilft.


1

Ich verstehe, was du meinst. Aus der Sicht des Designs eine Tabelle, die so aussieht:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

ist viel besser als eine Tabelle, die so aussieht:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Das Datenbankmodul kümmert sich jedoch nicht wirklich um Ihre logische Spaltenreihenfolge, wenn Sie eine tsql wie diese ausgeben:

SELECT FirstName, LastName, SSN FROM Employees

Die Engine weiß nur, wo die Liste der Vornamen auf der Festplatte gespeichert ist.

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.