Имеет ли значение порядок столбцов в определении таблицы?

35

При определении таблицы полезно упорядочить столбцы в логических группах и сами группы по назначению. Логическое упорядочение столбцов в таблице передает смысл разработчику и является элементом хорошего стиля.

Это понятно.

Однако неясно, оказывает ли логическое упорядочение столбцов в таблице какое-либо влияние на их физическое упорядочение на уровне хранилища, или оно оказывает какое-либо другое влияние, которое может беспокоить.

Помимо влияния на стиль, имеет ли значение порядок столбцов?

Есть вопрос о переполнении стека по этому поводу, но он не имеет авторитетного ответа.

Ник Чаммас
источник

Ответы:

23

Влияет ли логическое расположение столбцов в таблице на их физический порядок на уровне хранения? Да.

Имеет ли это значение или нет, это другой вопрос, на который я не могу ответить (пока).

Аналогично тому, как описано в часто цитируемой статье Пола Рэндала об анатомии записи , давайте рассмотрим простую таблицу из двух столбцов с 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

Вывод DBCC IND

Вывод выше показывает, что нам нужно взглянуть на страницу 89:

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

В выводе из DBCC PAGE мы видим, что c1 заполнен символом «A» перед «b» c2:

Memory Dump @0x000000000D25A060

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

И только потому, что давайте откроем бюст RowStructure.mdfс помощью шестнадцатеричного редактора и подтвердим, что строка «A» предшествует строке «B»:

AAAAAAAAAA

Теперь повторите тест, но измените порядок строк, поместив символы «B» в c1 и символы «A» в 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

На этот раз наш вывод DBCC PAGE отличается, и строка 'B' появляется первой:

Memory Dump @0x000000000FC2A060

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

Опять же, просто для смеха, давайте проверим шестнадцатеричный дамп файла данных:

BBBBBBBBBB

Как объясняет Анатомия Записи , столбцы фиксированной и переменной длины записи хранятся в отдельных блоках. Логическое чередование фиксированных и переменных типов столбцов не имеет никакого отношения к физической записи. Однако в каждом блоке порядок ваших столбцов соответствует порядку байтов в файле данных.

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

Смотрите также:

Порядок столбцов не имеет значения ... в общем, но - ЭТО ЗАВИСИТ!

Марк Стори-Смит
источник
+1 согласен Я всегда обнаруживал, что в каждом разделе порядок столбцов изначально соответствует CREATE TABLEинструкции (за исключением того, что ключевые столбцы CI стоят первыми в разделе). Хотя порядок столбцов может измениться, если ALTER COLUMNизменится тип данных / длина столбца. Единственный незначительный случай, когда мне кажется важным, это то, что столбцы в конце раздела переменной длины с пустой строкой или NULL вообще не занимают места в массиве смещений столбцов (продемонстрировано Kalen Delaney в книге внутренних данных 2008 года)
Мартин Смит
1
Порядок столбцов может иметь значение в редких угловых случаях. Например, если у вас есть таблица с 3 столбцами A, B и C, каждый длиной 3 КБ. Страницы SQL Server являются 8kb, поэтому Cне подходит, и входит в его собственной расширенной страницы. Так что select A, Bот YourTable` требуется только половина чтения страниц select A, C from YourTable.
Andomar
"Whether it matters or not is a different issue that I can't answer (yet).": Порядок столбцов может существенно повлиять на производительность. Более того, это может даже повлиять на ошибки! Проверьте это - Демонстрация 2 показывает это лучше, я думаю
Ронен Арили
@RonenAriely Интересный пример, но он несколько надуманный в контексте исходного вопроса. Вы демонстрируете, как порядок столбцов влияет на последующее удаление столбца. Я не думаю, что когда-либо проектировал таблицу с предвидением того, какие столбцы я опущу.
Марк Стори-Смит
Привет @ MarkStorey-Смит. (1) Как архитектор, я всегда объясняю, что различие между дизайном скважины и отличным дизайном заключается в том, что хороший дизайн обеспечивает текущие потребности, в то время как отличный дизайн обеспечивает будущие потребности, которые еще не известны. (2) Ответ на вопрос чистый ДА. Реализация ответа зависит от ФП и каждого из нас. Это выходит за рамки обсуждения, но мы можем открыть эту тему для обсуждения. Но не в семействе форумов stackoverflow, так как интерфейс не позволяет вести реальное обсуждение, а только добавляет одну-единственную плохую короткую строку текста в ответах
Ronen Ariely
7

Если вы не определите кластеризованный индекс, вы получите таблицу кучи. Для таблицы кучи вы всегда будете сканировать при чтении данных, и, таким образом, будут прочитаны все строки, что сделает порядок столбцов спорным.

Как только вы определите кластеризованный индекс, данные будут физически переставлены в соответствии с указанным вами физическим порядком столбцов, и на этом этапе физический порядок станет важным. Физический порядок - это то, что определяет соответствие оператора поиска на основе используемых вами предикатов.

Хотя я не могу вспомнить, чтобы когда-нибудь читал его, я бы предположил, что SQL Server не гарантирует физический порядок столбцов для куч, тогда как он будет гарантирован для индексов. Чтобы ответить на ваш вопрос, нет, порядок столбцов в определении не должен иметь значения, так как они не будут иметь значения при чтении данных (обратите внимание, что это только для куч - индексы - другое дело).

Обновление
На самом деле вы задаете два вопроса - «влияет ли логическое упорядочение столбцов в таблице на их физическое упорядочение на уровне хранилища» - нет. Логический порядок, определенный метаданными, не обязательно должен быть в том же порядке, что и физический. Насколько я понимаю, вы ищете ответ на вопрос, приводит ли логический порядок в CREATE TABLE к тому же физическому порядку при создании - который я не знаю, для куч - хотя с оговоркой выше.

Марк С. Расмуссен
источник
2

Исходя из того, что я видел и читал, порядок столбцов в SQL Server не имеет значения. Механизм хранения помещает столбцы в строку независимо от того, как они указаны в операторе CREATE TABLE. При этом, я уверен, что есть несколько очень изолированных крайних случаев, когда это имеет значение, но я думаю, что вам будет трудно получить однозначный ответ на эти вопросы. Пол Рэндал " Внутри хранилища«Категория постов в блоге - лучший источник всех подробностей о том, как работает механизм хранения, о которых я знаю. Я думаю, что вам придется изучить все различные способы работы хранилища и сопоставить их со всеми вариантами использования». чтобы найти граничные случаи, где порядок имеет значение. Если не указан конкретный граничный случай, который применим к моей ситуации, я просто логически упорядочиваю столбцы в CREATE TABLE. Надеюсь, это поможет.

Тод эверетт
источник
1

Я понимаю, что вы имеете в виду. С точки зрения дизайна таблица выглядит следующим образом:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

намного лучше, чем таблица, которая выглядит так:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Но движок базы данных на самом деле не заботится о порядке логических столбцов, если вы запускаете tsql, например так:

SELECT FirstName, LastName, SSN FROM Employees

Движок просто знает, где хранится список FirstName на диске.

MarlonRibunal
источник