Apakah urutan kolom dalam definisi tabel penting?

35

Saat mendefinisikan tabel, ada baiknya untuk memesan kolom dalam grup logis dan grup itu sendiri dengan sengaja. Urutan logis kolom dalam tabel menyampaikan makna kepada pengembang dan merupakan elemen gaya yang baik.

Itu jelas.

Namun, yang tidak jelas adalah apakah urutan logis kolom dalam tabel memiliki dampak pada urutan fisik mereka di lapisan penyimpanan, atau jika ada dampak lain yang mungkin diperhatikan.

Terlepas dari dampak pada gaya, apakah urutan kolom pernah penting?

Ada pertanyaan tentang Stack Overflow tentang ini, tetapi tidak memiliki jawaban yang otoritatif.

Nick Chammas
sumber

Jawaban:

23

Apakah urutan logis kolom dalam tabel memiliki dampak pada urutan fisik mereka di lapisan penyimpanan? Iya nih.

Apakah itu penting atau tidak adalah masalah yang berbeda yang belum bisa saya jawab (belum).

Dalam cara yang mirip dengan yang dijelaskan dalam artikel yang sering dikaitkan dari Paul Randal tentang anatomi catatan , mari kita lihat tabel dua kolom sederhana dengan 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

Output DBCC IND

Output di atas menunjukkan bahwa kita perlu melihat halaman 89:

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

Dalam output dari DBCC PAGE kita melihat c1 diisi dengan karakter 'A' sebelum c2's 'B':

Memory Dump @0x000000000D25A060

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

Dan hanya karena, mari kita buka RowStructure.mdfdengan editor hex dan konfirmasikan string 'A' mendahului string 'B':

AAAAAAAAAAA

Sekarang ulangi tes tetapi balik urutan string, menempatkan karakter 'B' di c1 dan karakter 'A' di 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

Kali ini output PAGE DBCC kami berbeda dan string 'B' muncul lebih dulu:

Memory Dump @0x000000000FC2A060

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

Sekali lagi, hanya untuk cekikikan, mari kita periksa hex dump dari file data:

BBBBBBBBBB

Seperti yang dijelaskan Anatomi Catatan , kolom panjang tetap dan variabel catatan disimpan dalam blok yang berbeda. Jenis kolom tetap dan variabel interleaving yang logis tidak memiliki kaitan dengan catatan fisik. Namun, dalam setiap blok urutan kolom Anda tidak memetakan ke urutan byte dalam file data.

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

Lihat juga:

Urutan kolom tidak masalah ... secara umum, tetapi - ITU TERGANTUNG!

Mark Storey-Smith
sumber
+1 Saya setuju. Saya selalu menemukan bahwa dalam setiap bagian urutan kolom awalnya sesuai dengan CREATE TABLEpernyataan (kecuali bahwa kolom kunci CI yang lebih dulu di bagian). Padahal urutan kolom bisa berubah jika ALTER COLUMNmengubah tipe data / panjang kolom. Satu-satunya kasus kecil di mana hal itu penting yang dapat saya pikirkan adalah bahwa kolom pada akhir bagian panjang variabel dengan string kosong atau NULL tidak mengambil ruang sama sekali dalam array kolom offset (ditunjukkan oleh Kalen Delaney dalam buku internal 2008)
Martin Smith
1
Urutan kolom bisa penting dalam kasus sudut langka. Misalnya, jika Anda memiliki tabel dengan 3 kolom A, B, dan C, masing-masing panjangnya 3kb byte. Halaman SQL Server adalah 8kb, jadi Ctidak cocok, dan masuk ke halaman diperpanjang sendiri. Jadi select A, Bdari YourTable` hanya membutuhkan setengah dari halaman yang dibaca select A, C from YourTable.
Andomar
"Whether it matters or not is a different issue that I can't answer (yet).": Urutan kolom dapat secara signifikan mempengaruhi kinerja. Selain itu, bahkan dapat memengaruhi kesalahan! Lihat ini - Demo 2 menunjukkannya lebih baik menurut saya
Ronen Ariely
@RonenAriely contoh yang menarik tetapi agak dibuat dalam konteks pertanyaan aslinya. Anda mendemonstrasikan bagaimana pesanan kolom berdampak ketika Anda kemudian menjatuhkan kolom. Saya tidak berpikir saya pernah merancang tabel dengan tinjauan ke depan kolom mana yang akan saya jatuhkan.
Mark Storey-Smith
Hai @ MarkStorey-Smith. (1) Sebagai seorang arsitek, saya selalu menjelaskan bahwa perbedaan antara desain sumur dan desain Hebat adalah desain yang baik menyediakan kebutuhan saat ini, sedangkan desain Hebat menyediakan kebutuhan masa depan yang belum diketahui. (2) Jawaban untuk pertanyaan adalah YA murni. Implementasi jawabannya terserah OP dan kita masing-masing. Ini di luar ruang lingkup diskusi, tetapi kita dapat membuka topik ini untuk diskusi. Tapi tidak di keluarga stackoverflow forum, karena antarmuka tidak memungkinkan untuk melakukan diskusi nyata tetapi hanya menambahkan satu baris pendek teks miskin dalam tanggapan
Ronen Ariely
7

Jika Anda tidak mendefinisikan indeks berkerumun, Anda akan mendapatkan tabel tumpukan. Untuk tabel tumpukan, Anda akan selalu memindai saat membaca data dan dengan demikian seluruh baris akan dibaca, menjadikan urutan kolom sebagai titik diperdebatkan.

Segera setelah Anda menentukan indeks berkerumun, data secara fisik disusun ulang agar sesuai dengan urutan fisik kolom seperti yang Anda tentukan - dan pada titik ini, urutan fisik menjadi penting. Urutan fisik adalah yang menentukan kelayakan operator yang mencari berdasarkan predikat yang Anda gunakan.

Meskipun saya tidak ingat pernah membacanya di mana saja, saya berasumsi SQL Server tidak menjamin urutan fisik kolom untuk tumpukan, sedangkan itu akan dijamin untuk indeks. Untuk menjawab pertanyaan Anda, tidak, urutan kolom dalam definisi seharusnya tidak masalah karena mereka tidak masalah ketika membaca data (perhatikan bahwa ini hanya untuk tumpukan - indeks adalah masalah yang berbeda).

Perbarui
Sebenarnya Anda mengajukan dua pertanyaan - "apakah urutan logis kolom dalam tabel memiliki dampak pada pemesanan fisik mereka di lapisan penyimpanan" adalah tidak. Urutan logis, sebagaimana didefinisikan oleh metadata, tidak harus berada dalam urutan yang sama dengan yang fisik. Apa yang saya kumpulkan Anda sedang mencari jawaban adalah apakah urutan logis dalam CREATE TABLE menghasilkan urutan fisik yang sama pada penciptaan - yang saya tidak tahu, untuk tumpukan - meskipun dengan peringatan di atas.

Mark S. Rasmussen
sumber
2

Berdasarkan apa yang saya lihat dan membaca urutan kolom di SQL Server tidak ada bedanya. Mesin penyimpanan menempatkan kolom pada baris terlepas dari bagaimana mereka ditentukan dalam pernyataan CREATE TABLE. Yang sedang berkata, saya yakin ada beberapa kasus tepi yang sangat terisolasi di mana itu penting tetapi saya pikir Anda akan mengalami kesulitan mendapatkan jawaban pasti tunggal untuk ini. Paul Randal " Inside The Storage Engine"Kategori posting blog adalah sumber terbaik untuk semua detail tentang cara kerja mesin penyimpanan yang saya sadari. Saya pikir Anda harus mempelajari semua cara penyimpanan dan matriks yang bertentangan dengan semua kasus penggunaan." untuk menemukan kasus tepi di mana pesanan akan menjadi masalah. Kecuali jika kasus tepi tertentu ditunjukkan yang berlaku untuk situasi saya, saya hanya memesan kolom secara logis pada CREATE TABLE saya.

Todd Everett
sumber
1

Saya paham apa yang kamu maksud. Dari perspektif desain, tabel yang terlihat seperti ini:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

jauh lebih baik daripada tabel yang terlihat seperti ini:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Tetapi mesin Database tidak terlalu peduli dengan urutan kolom logis Anda jika Anda mengeluarkan tsql seperti ini:

SELECT FirstName, LastName, SSN FROM Employees

Mesin hanya tahu di mana daftar FirstName disimpan di disk.

MarlonRibunal
sumber