A ordem das colunas na definição de uma tabela é importante?

35

Ao definir uma tabela, é útil ordenar as colunas em grupos lógicos e os próprios grupos por finalidade. A ordem lógica das colunas em uma tabela transmite significado ao desenvolvedor e é um elemento de bom estilo.

Isso está claro.

O que não está claro, no entanto, é se a ordem lógica das colunas em uma tabela tem algum impacto em sua ordem física na camada de armazenamento ou se tem algum outro impacto que possa interessar.

Além do impacto no estilo, a ordem das colunas é importante?

Há uma pergunta no Stack Overflow sobre isso, mas falta uma resposta autorizada.

Nick Chammas
fonte

Respostas:

23

A ordem lógica das colunas em uma tabela tem algum impacto em sua ordem física na camada de armazenamento? Sim.

Se importa ou não, é uma questão diferente que ainda não posso responder.

De maneira semelhante à descrita no artigo frequentemente vinculado de Paul Randal sobre a anatomia de um registro , vejamos uma tabela simples de duas colunas com 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

Saída DBCC IND

A saída acima mostra que precisamos olhar para a página 89:

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

Na saída do DBCC PAGE, vemos c1 recheado com o caractere 'A' antes dos c2's 'B':

Memory Dump @0x000000000D25A060

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

E apenas porque, vamos abrir RowStructure.mdfcom um editor hexadecimal e confirmar que a string 'A' precede a string 'B':

AAAAAAAAAA

Agora repita o teste, mas inverta a ordem das seqüências, colocando os caracteres 'B' em c1 e os caracteres 'A' em 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

Desta vez, nossa saída DBCC PAGE é diferente e a string 'B' aparece primeiro:

Memory Dump @0x000000000FC2A060

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

Novamente, apenas para rir, vamos verificar o hex dump do arquivo de dados:

BBBBBBBBBB

Como Anatomia de um registro explica, as colunas de comprimento fixo e variável de um registro são armazenadas em blocos distintos. A intercalação lógica de tipos de coluna fixa e variável não influencia o registro físico. No entanto, dentro de cada bloco, a ordem das suas colunas é mapeada para a ordem dos bytes no arquivo de dados.

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

Veja também:

A ordem das colunas não importa ... geralmente, mas - DEPENDE!

Mark Storey-Smith
fonte
+1 eu concordo. Sempre achei que, dentro de cada seção, a ordem das colunas inicialmente é de acordo com a CREATE TABLEinstrução (exceto que as colunas-chave do IC vêm primeiro na seção). Embora a ordem das colunas possa mudar se os ALTER COLUMNtipos de dados / comprimento das colunas forem alterados. O único caso menor em que importa que eu possa pensar é que as colunas no final da seção de comprimento variável com string vazia ou NULL não ocupam espaço algum na matriz de deslocamento de coluna (demonstrada por Kalen Delaney no livro de 2008)
Martin Smith
11
A ordem das colunas pode importar em casos de canto raros. Por exemplo, se você tiver uma tabela com 3 colunas A, B e C, cada um com 3 KB de bytes. As páginas do SQL Server têm 8kb, portanto Cnão se ajustam e entram em sua própria página estendida. Portanto, select A, Bem YourTable`, apenas metade da página é lida select A, C from YourTable.
Andomar
"Whether it matters or not is a different issue that I can't answer (yet).": A ordem das colunas pode afetar significativamente o desempenho. Além disso, pode até causar erros! Verifique isto - Demo 2 mostra melhor, eu acho
Ronen Ariely 23/03
@RonenAriely Exemplo interessante, mas é um tanto artificial no contexto da pergunta original. Você está demonstrando como a ordem das colunas afeta quando você solta a coluna posteriormente. Acho que nunca projetei uma tabela com previsão de quais colunas vou largar.
Mark Storey-Smith
Olá, @ MarkStorey-Smith. (1) Como arquiteto, eu sempre explico que a diferença entre design de poço e design ótimo é que o bom design fornece as necessidades atuais, enquanto o design ótimo fornece as necessidades futuras que ainda não são conhecidas. (2) A resposta para a pergunta é pura SIM. A implementação da resposta depende do OP e de cada um de nós. Isso está fora do escopo da discussão, mas podemos abrir este tópico para discussão. Mas não na família de fóruns stackoverflow, pois a interface não permite ter uma discussão real, mas apenas adiciona uma única linha curta de texto ruim nas respostas
Ronen Ariely
7

Se você não definir um índice em cluster, receberá uma tabela de heap. Para uma tabela de heap, você sempre fará a varredura ao ler dados e, portanto, as linhas inteiras serão lidas, tornando a ordem das colunas um ponto discutível.

Assim que você define um índice em cluster, os dados são fisicamente reorganizados para estar em conformidade com a ordem física das colunas conforme você especifica - e, nesse ponto, a ordem física se torna importante. A ordem física é o que determina a elegibilidade do operador que procura, com base nos predicados que você está usando.

Embora eu não me lembre de lê-lo em qualquer lugar, presumo que o SQL Server não garanta a ordem física das colunas para os heaps, enquanto isso será garantido para os índices. Para responder sua pergunta, não, a ordem das colunas na definição não deve importar, pois não importa ao ler os dados (observe que isso é apenas para pilhas - índices são uma questão diferente).

Atualização
Na verdade, você está fazendo duas perguntas - "se a ordem lógica das colunas em uma tabela tem algum impacto em sua ordem física na camada de armazenamento" é um não. A ordem lógica, conforme definida pelos metadados, não precisa estar na mesma ordem que a física. O que eu acho que você está procurando uma resposta é se a ordem lógica na CREATE TABLE resulta na mesma ordem física na criação - que eu não conheço, para montões - embora com a ressalva acima.

Mark S. Rasmussen
fonte
2

Com base no que vi e li, a ordenação de colunas no SQL Server não faz diferença. O mecanismo de armazenamento coloca colunas na linha, independentemente de como elas são especificadas na instrução CREATE TABLE. Dito isto, tenho certeza de que há alguns casos extremos muito isolados onde isso importa, mas acho que será difícil obter uma resposta definitiva sobre eles. Paul Randal " dentro do mecanismo de armazenamento"a categoria de postagens do blog é a melhor fonte de todos os detalhes sobre como o mecanismo de armazenamento funciona. Eu acho que você precisaria estudar todas as várias maneiras pelas quais o armazenamento funciona e a matriz em relação a todos os casos de uso para encontrar os casos em que a ordem importaria, a menos que seja indicado um caso específico que se aplique à minha situação, eu apenas ordeno as colunas logicamente na minha CREATE TABLE.

Todd Everett
fonte
1

Eu entendi o que você quis dizer. Da perspectiva do design, uma tabela que se parece com isso:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

é muito melhor do que uma tabela que se parece com isso:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Mas o mecanismo de banco de dados não se importa realmente com a ordem da coluna lógica se você emitir um tsql como este:

SELECT FirstName, LastName, SSN FROM Employees

O mecanismo apenas sabe onde a lista de nomes está armazenada no disco.

MarlonRibunal
fonte