Чи має значення порядок стовпців у визначенні таблиці?


35

Визначаючи таблицю, корисно впорядкувати стовпці в логічних групах та самих групах за призначенням. Логічне впорядкування стовпців у таблиці передає значення розробнику і є елементом гарного стилю.

Це зрозуміло.

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

Окрім впливу на стиль, чи має значення порядок стовпців?

Про Stack Overflow є питання про це, але на це не вистачає авторитетної відповіді.

Відповіді:


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' перед c2 'B':

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 взагалі не займають місця в масиві зміщення стовпців (продемонстровано Каленом Делані в книзі внутрішніх справ 2008 року)
Мартін Сміт

1
Порядок стовпців може мати значення в рідкісних кутових випадках. Наприклад, якщо у вас є таблиця з 3 стовпцями A, B і C, кожен байт довжиною 3 кбіт. Сторінки SQL Server розміром 8 кб, тому Cне підходять, і переходять на свою розширену сторінку. Отже, select A, Bвід YourTable` потрібно лише половину прочитаних сторінок select A, C from YourTable.
Андомар

"Whether it matters or not is a different issue that I can't answer (yet).": Порядок стовпців може суттєво вплинути на продуктивність. Крім того, це навіть може вплинути на помилки! Перевірте це - Демо 2 показує, що краще я думаю
Ронен Аріелі

@RonenAriely Цікавий приклад, але він дещо задуманий у контексті оригінального питання. Ви демонструєте, як порядок стовпців впливає, коли згодом ви скинете стовпець. Я не думаю, що я ніколи не розробляв таблицю з передбаченням, які колони я опускатиму.
Марк Сторі-Сміт

Привіт @ MarkStorey-Smith. (1) Як архітектор я завжди пояснюю, що різниця між дизайном свердловин та Великим дизайном полягає в тому, що хороший дизайн забезпечує поточні потреби, тоді як Великий дизайн забезпечує майбутні потреби, які ще не відомі. (2) Відповідь на питання чистий ТАК. Реалізація відповіді залежить від ОП та кожного з нас. Це поза сферою обговорення, але ми можемо відкрити цю тему для обговорення. Але не в сім'ї форумів stackoverflow, оскільки інтерфейс не дозволяє реально обговорювати, а лише додає у відповіді єдиний короткий короткий рядок тексту
Ronen Ariely

7

Якщо ви не визначите кластерний індекс, ви отримаєте таблицю купи. У таблиці купи ви завжди будете сканувати під час читання даних, і таким чином будуть читатися цілі рядки, перетворюючи порядок стовпців на точку суперечки.

Щойно ви визначаєте кластерний індекс, дані фізично переставляють на відповідність фізичному порядку стовпців, як ви вказуєте, - і в цей момент фізичний порядок стає важливим. Фізичний порядок визначає придатність шукаючого оператора на основі предикатів, які ви використовуєте.

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

Оновлення
Насправді ви задаєте два питання - "чи логічне впорядкування стовпців у таблиці впливає на їх фізичне упорядкування на рівні зберігання" - це "ні". Логічний порядок, визначений метаданими, не повинен бути в тому ж порядку, як фізичний. Що я збираю, ти шукаєш відповідь, чи логічний порядок у СТВОРЕННІЙ СТОЛІ приводить до того ж фізичного порядку щодо створення - якого я не знаю, для купи - хоч із застереженням вище.


2

Виходячи з того, що я бачив і читав, впорядкування стовпців у SQL Server не має ніякої різниці. Двигун зберігання розміщує стовпці у рядку незалежно від того, як вони вказані у операторі CREATE TABLE. Зважаючи на це, я впевнений, що є дуже окремі крайні випадки, коли це має значення, але я думаю, що вам буде важко отримати однозначну відповідь на це. Пола Рандала « Всередині двигуна зберігання"Категорія публікацій блогу - найкраще джерело для всіх деталей про те, як працює двигун зберігання даних, про що я знаю. Я думаю, вам доведеться вивчити всі різні способи роботи сховища та матрицю, що проти всіх випадків використання щоб знайти крайні випадки, де порядок мав би значення. Якщо не вказано конкретний край, який стосується моєї ситуації, я просто замовляю стовпці логічно на СВОЄМО СТОЛІ. Сподіваюся, це допоможе.


1

Я розумію, що ти маєш на увазі. З точки зору дизайну таблиця, яка виглядає приблизно так:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

набагато краще, ніж таблиця, яка виглядає так:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Але двигун бази даних насправді не дбає про ваш логічний порядок стовпців, якщо ви видаєте такий tsql, як цей:

SELECT FirstName, LastName, SSN FROM Employees

Двигун просто знає, де список диска FirstName зберігається на диску.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.