Czy kolejność kolumn w definicji tabeli ma znaczenie?


35

Podczas definiowania tabeli pomocne jest uporządkowanie kolumn w grupach logicznych i samych grup według celu. Logiczne uporządkowanie kolumn w tabeli przekazuje znaczenie deweloperowi i jest elementem dobrego stylu.

To jasne.

Nie jest jednak jasne, czy logiczne uporządkowanie kolumn w tabeli ma jakikolwiek wpływ na ich fizyczne uporządkowanie w warstwie pamięci, czy też ma inny wpływ, na który można się zwrócić.

Czy oprócz wpływu na styl, kolejność kolumn ma kiedykolwiek znaczenie?

Jest na to pytanie dotyczące przepełnienia stosu , ale brakuje wiarygodnej odpowiedzi.

Odpowiedzi:


23

Czy logiczne uporządkowanie kolumn w tabeli ma wpływ na ich porządek fizyczny w warstwie pamięci? Tak.

To, czy to ważne, czy nie, to inna kwestia, na którą nie mogę (jeszcze) odpowiedzieć.

W sposób podobny do opisanego w często łączonym artykule Paula Randala na temat anatomii rekordu , spójrzmy na prostą tabelę dwóch kolumn z DBCC IND:

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

Wyjście DBCC IND

Powyższy wynik pokazuje, że musimy spojrzeć na stronę 89:

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

Na wyjściu z STRONY DBCC widzimy c1 wypchany znakiem „A” przed „B” c2:

Memory Dump @0x000000000D25A060

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

I tylko dlatego, że pozwala otworzyć biust RowStructure.mdfza pomocą edytora szesnastkowego i potwierdzić, że ciąg „A” poprzedza ciąg „B”:

AAAAAAAAAA

Teraz powtórz test, ale odwróć kolejność ciągów, umieszczając znaki „B” w c1 i znaki „A” w c2:

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

Tym razem nasze wyjście DBCC PAGE jest inne i ciąg „B” pojawia się jako pierwszy:

Memory Dump @0x000000000FC2A060

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

Ponownie, tylko na chichoty, sprawdźmy zrzut heksadecymalny pliku danych:

BBBBBBBBBB

Jak wyjaśnia anatomia rekordu , kolumny rekordu o stałej i zmiennej długości są przechowywane w odrębnych blokach. Logicznie przeplatane stałe i zmienne typy kolumn nie mają wpływu na zapis fizyczny. Jednak w każdym bloku kolejność kolumn jest odwzorowana na kolejność bajtów w pliku danych.

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

Zobacz też:

Kolejność kolumn nie ma znaczenia… ogólnie, ale - ZALEŻY!


+1 Zgadzam się. Zawsze znajdowałem, że w każdej sekcji kolejność kolumn początkowo jest zgodna z CREATE TABLEinstrukcją (z wyjątkiem tego, że kolumny klucza CI są pierwsze w sekcji). Chociaż kolejność kolumn może ulec zmianie, jeśli ALTER COLUMNzmieni się typy danych / długości kolumn. Jedyny drobny przypadek, w którym ma znaczenie, o którym mogę myśleć, to to, że kolumny na końcu sekcji o zmiennej długości z pustym łańcuchem lub wartością NULL nie zajmują wcale miejsca w tablicy przesunięć kolumn (wykazane przez Kalen Delaney w książce dotyczącej elementów wewnętrznych z 2008 r.)
Martin Smith

1
W rzadkich przypadkach narożnych kolejność kolumn może mieć znaczenie. Na przykład, jeśli masz tabelę z 3 kolumnami A, B i C, każda ma długość 3 KB. Strony programu SQL Server mają rozmiar 8 KB, więc Cnie pasują i przechodzą na własną rozszerzoną stronę. Zatem select A, Bz YourTable` wymaga tylko połowa odczytów strony select A, C from YourTable.
Andomar

"Whether it matters or not is a different issue that I can't answer (yet).": Kolejność kolumn może znacząco wpływać na wydajność, a nawet wpływać na błędy! Sprawdź to - Demo 2 pokazuje to lepiej, myślę
Ronen Ariely

@RonenAriely Interesujący przykład, ale jest nieco wymyślony w kontekście pierwotnego pytania. Demonstrujesz wpływ kolejności kolumn, gdy później upuścisz kolumnę. Nie sądzę, żebym kiedykolwiek zaprojektował stół, który przewidywałby, które kolumny upuszczę.
Mark Storey-Smith

Cześć @ MarkStorey-Smith. (1) Jako architekt zawsze wyjaśniam, że różnica między studnią studni a projektowaniem wielkim polega na tym, że dobry projekt zaspokaja obecne potrzeby, podczas gdy projekt wielki zapewnia przyszłe potrzeby, które nie są jeszcze znane. (2) Odpowiedź na pytanie brzmi TAK. Realizacja odpowiedzi zależy od PO i każdego z nas. Jest to poza zakresem dyskusji, ale możemy otworzyć ten temat do dyskusji. Ale nie w rodzinie forów stackoverflow, ponieważ interfejs nie pozwala na prawdziwą dyskusję, ale dodaje tylko jedną kiepską krótką linię tekstu w odpowiedziach
Ronen Ariely

7

Jeśli nie zdefiniujesz indeksu klastrowego, otrzymasz tabelę sterty. W przypadku tabeli stert zawsze będziesz skanować podczas odczytu danych, a tym samym zostaną odczytane całe wiersze, co sprawi, że kolejność kolumn stanie się kwestią sporną.

Jak tylko zdefiniujesz indeks klastrowy, dane są fizycznie przestawiane w celu dostosowania do fizycznej kolejności kolumn, jak określisz - i w tym momencie kolejność fizyczna staje się ważna. Porządek fizyczny decyduje o kwalifikowalności operatora szukającego na podstawie używanych predykatów.

Chociaż nigdzie nie pamiętam, by go czytać, zakładam, że SQL Server nie gwarantuje fizycznej kolejności kolumn dla stosów, podczas gdy będzie to gwarantowane dla indeksów. Aby odpowiedzieć na twoje pytanie, nie, kolejność kolumn w definicji nie powinna mieć znaczenia, ponieważ nie będą miały znaczenia podczas odczytu danych (pamiętaj, że jest to tylko hałd - indeksy to inna sprawa).

Aktualizacja
Właściwie zadajesz dwa pytania - „czy logiczne uporządkowanie kolumn w tabeli ma wpływ na ich fizyczne uporządkowanie w warstwie pamięci” jest nie. Kolejność logiczna, zgodnie z definicją metadanych, nie musi być w tej samej kolejności, co fizyczna. Zbieram, że szukam odpowiedzi na to, czy logiczny porządek w tabeli TWORZENIA STABILNOŚCI skutkuje tym samym porządkiem fizycznym przy tworzeniu - czego nie znam na stosach - chociaż z powyższym zastrzeżeniem.


2

Na podstawie tego, co widziałem i czytałem, porządkowanie kolumn w SQL Server nie ma znaczenia. Mechanizm pamięci masowej umieszcza kolumny w wierszu niezależnie od tego, jak są określone w instrukcji CREATE TABLE. Biorąc to pod uwagę, jestem pewien, że istnieją pewne bardzo odosobnione przypadki brzegowe, w których ma to znaczenie, ale myślę, że będzie ci trudno uzyskać jedną ostateczną odpowiedź na te pytania. „ Inside The Storage Engine ” Paula Randala„Kategoria postów na blogu jest najlepszym źródłem wszystkich szczegółów na temat tego, jak działa silnik pamięci, o których wiem. Myślę, że musiałbyś przestudiować wszystkie różne sposoby działania magazynu i matrycę w porównaniu do wszystkich przypadków użycia aby znaleźć przypadki krawędzi, w których kolejność miałaby znaczenie. O ile nie wskazano konkretnego przypadku krawędzi, który dotyczy mojej sytuacji, po prostu logicznie porządkuję kolumny w moim CREATE TABLE. Mam nadzieję, że to pomoże.


1

Rozumiem co masz na myśli. Z perspektywy projektowania tabela wygląda następująco:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

jest o wiele lepszy niż stół, który wygląda następująco:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Ale aparat bazy danych tak naprawdę nie przejmuje się logiczną kolejnością kolumn, jeśli wydasz tsql w ten sposób:

SELECT FirstName, LastName, SSN FROM Employees

Mechanizm po prostu wie, gdzie znajduje się lista FirstName na dysku.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.