È importante l'ordine delle colonne nella definizione di una tabella?


35

Quando si definisce una tabella, è utile ordinare le colonne in gruppi logici e i gruppi stessi per scopo. L'ordinamento logico delle colonne in una tabella trasmette significato allo sviluppatore ed è un elemento di buon stile.

Questo è chiaro

Ciò che non è chiaro, tuttavia, è se l'ordinamento logico delle colonne in una tabella ha un impatto sul loro ordinamento fisico a livello di archiviazione o se ha qualsiasi altro impatto di cui ci si potrebbe preoccupare.

A parte l'impatto sullo stile, l'ordine delle colonne ha mai importanza?

C'è una domanda su Stack Overflow a riguardo, ma manca una risposta autorevole.

Risposte:


23

L'ordinamento logico delle colonne in una tabella ha un impatto sul loro ordine fisico a livello di memoria? Sì.

Che sia importante o meno è un problema diverso a cui non posso rispondere (ancora).

In modo simile a quello descritto nell'articolo collegato di frequente di Paul Randal sull'anatomia di un disco , diamo un'occhiata a una semplice tabella a due colonne con 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

Uscita DBCC IND

L'output sopra mostra che dobbiamo guardare a pagina 89:

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

Nell'output di DBCC PAGE vediamo c1 riempito con il carattere 'A' prima della 'B' di c2:

Memory Dump @0x000000000D25A060

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

E proprio perché, apriamo il busto RowStructure.mdfcon un editor esadecimale e confermiamo che la stringa 'A' precede la stringa 'B':

AAAAAAAAAA

Ora ripeti il ​​test ma inverti l'ordine delle stringhe, posizionando i caratteri 'B' in c1 e i caratteri 'A' in 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

Questa volta il nostro output di DBCC PAGE è diverso e la stringa 'B' appare per prima:

Memory Dump @0x000000000FC2A060

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

Ancora una volta, solo per ridacchiare, controlliamo il dump esadecimale del file di dati:

bbbbbbbbbb

Come spiega Anatomy of a Record , le colonne a lunghezza fissa e variabile di un record sono memorizzate in blocchi distinti. I tipi di colonne fisse e variabili interleaving logicamente non influiscono sul record fisico. Tuttavia, all'interno di ciascun blocco l'ordine delle colonne viene mappato all'ordine dei byte nel file di dati.

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

Guarda anche:

L'ordine delle colonne non ha importanza ... in generale, ma - DIPENDE!


+1 Sono d'accordo. Ho sempre scoperto che all'interno di ciascuna sezione l'ordine delle colonne inizialmente è come da CREATE TABLEistruzione (tranne che le colonne chiave CI vengono prima nella sezione). Sebbene l'ordine delle colonne possa cambiare se si ALTER COLUMNmodificano tipi di dati / lunghezze delle colonne. L'unico caso minore in cui mi viene in mente che mi viene in mente che le colonne alla fine della sezione di lunghezza variabile con stringa vuota o NULL non occupano affatto spazio nell'array offset di colonna (dimostrato da Kalen Delaney nel libro degli interni del 2008)
Martin Smith,

1
L'ordine delle colonne può avere importanza in rari casi d'angolo. Ad esempio, se si dispone di una tabella con 3 colonne A, B e C, ciascuna di 3 KB di byte. Le pagine di SQL Server sono 8kb, quindi Cnon si adattano e vanno nella sua pagina estesa. Quindi select A, Bda YourTable` richiede solo metà della lettura della pagina select A, C from YourTable.
Andomar,

"Whether it matters or not is a different issue that I can't answer (yet).": L'ordine delle colonne può influire in modo significativo sulle prestazioni. Inoltre, può anche influire sugli errori!
Dai un'occhiata a

@RonenAriely Esempio interessante ma è in qualche modo inventato nel contesto della domanda originale. Stai dimostrando come l'ordine delle colonne ha un impatto quando successivamente lasci cadere la colonna. Non credo di aver mai progettato una tabella con lungimiranza di quali colonne lascerò cadere.
Mark Storey-Smith,

Ciao @ MarkStorey-Smith. (1) In qualità di architetto, spiego sempre che la differenza tra design bene e grande design è che un buon design fornisce le esigenze attuali, mentre il grande design fornisce le esigenze future che non sono ancora note. (2) La risposta alla domanda è SÌ. L'implementazione della risposta spetta al PO e a ciascuno di noi. Ciò non rientra nell'ambito della discussione, ma possiamo aprire questo argomento per la discussione. Ma non nella famiglia di forum StackOverflow, poiché l'interfaccia non consente di avere una vera discussione, ma aggiunge solo una breve breve riga di testo nelle risposte
Ronen Ariely

7

Se non si definisce un indice cluster, verrà visualizzata una tabella heap. Per una tabella heap eseguirai sempre la scansione durante la lettura dei dati e quindi verranno lette tutte le righe, rendendo l'ordine delle colonne un punto controverso.

Non appena si definisce un indice cluster, i dati vengono riorganizzati fisicamente per conformarsi all'ordine fisico delle colonne come specificato - e a questo punto, l'ordine fisico diventa importante. L'ordine fisico è ciò che determina l'idoneità dell'operatore che cerca in base ai predicati che stai utilizzando.

Anche se non ricordo di averlo letto da nessuna parte, suppongo che SQL Server non garantisca l'ordine fisico delle colonne per gli heap, mentre sarà garantito per gli indici. Per rispondere alla tua domanda, no, l'ordine delle colonne nella definizione non dovrebbe avere importanza in quanto non contano durante la lettura dei dati (nota che questo è solo per i cumuli: gli indici sono una questione diversa).

Aggiornamento
In realtà stai ponendo due domande: "se l'ordinamento logico delle colonne in una tabella ha un impatto sul loro ordinamento fisico a livello di memoria" è un no. L'ordine logico, come definito dai metadati, non deve essere nello stesso ordine di quello fisico. Ciò a cui racconto che stai cercando una risposta è se l'ordine logico in CREATE TABLE si traduce nello stesso ordine fisico sulla creazione - che non conosco, per un mucchio - sebbene con l'avvertenza sopra.


2

Sulla base di ciò che ho visto e letto l'ordinamento delle colonne in SQL Server non fa differenza. Il motore di archiviazione posiziona le colonne sulla riga indipendentemente da come sono specificate nell'istruzione CREATE TABLE. Detto questo, sono sicuro che ci sono alcuni casi limite molto isolati in cui è importante, ma penso che avrai difficoltà a ottenere una risposta definitiva su questi. " Inside The Storage Engine " di Paul Randal"La categoria di post sul blog è la migliore fonte per tutti i dettagli su come funziona il motore di archiviazione di cui sono a conoscenza. Penso che dovresti studiare tutti i vari modi in cui funziona lo storage e la matrice rispetto a tutti i casi d'uso per trovare i casi limite in cui l'ordine avrebbe importanza. A meno che non venga indicato un caso limite specifico che si applica alla mia situazione, ordino logicamente le colonne sulla mia CREATE TABLE. Spero che questo aiuti.


1

Capisco quello che vuoi intendere. Dal punto di vista del design un tavolo che assomiglia a questo:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

è molto meglio di un tavolo che assomiglia a questo:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Ma il motore di database non si preoccupa davvero del tuo ordine di colonne logiche se emetti un tsql come questo:

SELECT FirstName, LastName, SSN FROM Employees

Il motore sa solo dove è memorizzato l'elenco di FirstName sul disco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.