Thứ tự của các cột trong định nghĩa của bảng có quan trọng không?


35

Khi xác định một bảng, thật hữu ích khi sắp xếp các cột theo các nhóm logic và các nhóm theo mục đích. Thứ tự logic của các cột trong bảng truyền tải ý nghĩa cho nhà phát triển và là một yếu tố của phong cách tốt.

Thế là rõ ràng.

Tuy nhiên, điều không rõ ràng là liệu thứ tự logic của các cột trong bảng có bất kỳ tác động nào đến thứ tự vật lý của chúng ở lớp lưu trữ hay không, nếu nó có bất kỳ tác động nào khác mà người ta có thể quan tâm.

Ngoài tác động đến phong cách, thứ tự cột có bao giờ quan trọng?

Có một câu hỏi trên Stack Overflow về điều này, nhưng nó thiếu một câu trả lời có thẩm quyền.

Câu trả lời:


23

Thứ tự logic của các cột trong bảng có bất kỳ tác động nào đến trật tự vật lý của chúng ở lớp lưu trữ không? Vâng.

Cho dù nó có quan trọng hay không là một vấn đề khác mà tôi không thể trả lời (chưa).

Theo cách tương tự như được mô tả trong bài viết được liên kết thường xuyên từ Paul Randal về giải phẫu của một bản ghi , chúng ta hãy xem một bảng hai cột đơn giản với 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

Đầu ra DBCC IND

Đầu ra ở trên cho thấy rằng chúng ta cần xem trang 89:

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

Trong đầu ra từ TRANG DBCC, chúng ta thấy c1 được nhồi với ký tự 'A' trước c2 'B':

Memory Dump @0x000000000D25A060

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

Và chỉ vì, cho phép mở RowStructure.mdfbằng trình chỉnh sửa hex và xác nhận chuỗi 'A' trước chuỗi 'B':

AAAAAAAAAA

Bây giờ lặp lại thử nghiệm nhưng đảo ngược thứ tự của các chuỗi, đặt các ký tự 'B' vào c1 và các ký tự 'A' trong 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

Lần này, đầu ra TRANG DBCC của chúng tôi khác và chuỗi 'B' xuất hiện đầu tiên:

Memory Dump @0x000000000FC2A060

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

Một lần nữa, chỉ để cười khúc khích, hãy kiểm tra kết xuất hex của tệp dữ liệu:

BBBBBBBB

Như Anatomy of a Record giải thích, các cột có chiều dài cố định và thay đổi của bản ghi được lưu trữ trong các khối riêng biệt. Hợp lý xen kẽ các loại cột cố định và biến đổi không có ảnh hưởng đến hồ sơ vật lý. Tuy nhiên, trong mỗi khối, thứ tự các cột của bạn sẽ ánh xạ tới thứ tự byte trong tệp dữ liệu.

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

Xem thêm:

Thứ tự cột không quan trọng nói chung, nhưng - TIỀN GỬI CNTT!


Tôi đồng ý. Tôi luôn thấy rằng trong mỗi phần, thứ tự của các cột ban đầu là theo CREATE TABLEcâu lệnh (ngoại trừ các cột khóa CI xuất hiện đầu tiên trong phần). Mặc dù thứ tự của các cột có thể thay đổi nếu ALTER COLUMNthay đổi kiểu dữ liệu / độ dài cột. Trường hợp nhỏ duy nhất mà tôi có thể nghĩ đến là các cột ở cuối phần có độ dài thay đổi với chuỗi rỗng hoặc NULL không có khoảng trống nào trong mảng bù cột (được Kalen Delaney trình bày trong sách nội bộ 2008)
Martin Smith

1
Thứ tự cột có thể quan trọng trong trường hợp góc hiếm. Ví dụ: nếu bạn có một bảng có 3 cột A, B và C, mỗi cột dài 3kb. Các trang SQL Server là 8kb, vì vậy Ckhông phù hợp và đi vào trang mở rộng của riêng nó. Vì vậy, select A, Btừ YourTable` chỉ yêu cầu một nửa số trang đọc select A, C from YourTable.
Andomar

"Whether it matters or not is a different issue that I can't answer (yet).": Thứ tự các cột có thể ảnh hưởng đáng kể đến hiệu suất. Hơn nữa, Nó thậm chí có thể ảnh hưởng đến các lỗi! Kiểm tra cái này - Demo 2 cho thấy nó tốt hơn tôi nghĩ
Ronen Ariely

@RonenAriely Ví dụ thú vị nhưng nó phần nào được đặt ra trong bối cảnh của câu hỏi ban đầu. Bạn đang trình bày cách thứ tự cột có tác động khi bạn sau đó thả cột. Tôi không nghĩ rằng tôi đã từng thiết kế một bảng với tầm nhìn xa mà cột tôi sẽ thả.
Mark Storey-Smith

Xin chào @ MarkStorey-Smith. (1) Là một kiến ​​trúc sư, tôi luôn giải thích rằng sự khác biệt giữa thiết kế giếng và thiết kế tuyệt vời là thiết kế tốt cung cấp các nhu cầu hiện tại, trong khi thiết kế tuyệt vời cung cấp các nhu cầu trong tương lai chưa được biết đến. (2) Câu trả lời cho câu hỏi hoàn toàn CÓ. Việc thực hiện câu trả lời là tùy thuộc vào OP và mỗi người chúng ta. Điều này nằm ngoài phạm vi thảo luận, nhưng chúng ta có thể mở chủ đề này để thảo luận. Nhưng không phải tại gia đình diễn đàn stackoverflow, vì giao diện không cho phép có một cuộc thảo luận thực sự mà chỉ thêm một dòng văn bản ngắn nghèo nàn trong các phản hồi
Ronen Ariely

7

Nếu bạn không xác định một chỉ mục được nhóm, bạn sẽ nhận được một bảng heap. Đối với bảng heap, bạn sẽ luôn quét khi đọc dữ liệu và do đó toàn bộ các hàng sẽ được đọc, hiển thị thứ tự các cột thành một điểm cần thiết.

Ngay khi bạn xác định một chỉ mục được nhóm, dữ liệu được sắp xếp lại theo vật lý để phù hợp với thứ tự vật lý của các cột khi bạn chỉ định - và tại thời điểm này, thứ tự vật lý trở nên quan trọng. Thứ tự vật lý là yếu tố quyết định tính đủ điều kiện của nhà điều hành tìm kiếm dựa trên các vị từ bạn đang sử dụng.

Mặc dù tôi không thể nhớ đọc nó ở bất cứ đâu, tôi cho rằng SQL Server không đảm bảo thứ tự vật lý của các cột cho heap, trong khi nó sẽ được đảm bảo cho các chỉ mục. Để trả lời câu hỏi của bạn, không, thứ tự của các cột trong định nghĩa sẽ không quan trọng vì chúng không quan trọng khi đọc dữ liệu (lưu ý rằng điều này chỉ dành cho heaps - chỉ mục là một vấn đề khác).

Cập nhật
Trên thực tế, bạn đang hỏi hai câu hỏi - "liệu thứ tự logic của các cột trong bảng có bất kỳ tác động nào đến thứ tự vật lý của chúng ở lớp lưu trữ hay không" là không. Thứ tự logic, như được xác định bởi siêu dữ liệu, không nhất thiết phải theo thứ tự như thứ tự vật lý. Những gì tôi thu thập được bạn đang tìm kiếm một câu trả lời là liệu thứ tự logic trong CREATE TABLE có kết quả theo thứ tự vật lý tương tự khi tạo - mà tôi không biết, cho các đống - mặc dù có cảnh báo ở trên.


2

Dựa trên những gì tôi đã thấy và đọc thứ tự các cột trong SQL Server không có sự khác biệt. Công cụ lưu trữ đặt các cột trên hàng bất kể chúng được chỉ định như thế nào trong câu lệnh CREATE TABLE. Điều đó đang được nói, tôi chắc chắn có một số trường hợp cạnh rất cô lập, nhưng nó nghĩ rằng bạn sẽ có một thời gian khó khăn để có được một câu trả lời dứt khoát về những điều này. " Bên trong công cụ lưu trữ của Paul Randal""danh mục bài đăng trên blog là nguồn tốt nhất cho tất cả các chi tiết về cách thức hoạt động của công cụ lưu trữ mà tôi biết. Tôi nghĩ bạn sẽ phải nghiên cứu tất cả các cách khác nhau để lưu trữ hoạt động và ma trận chống lại tất cả các trường hợp sử dụng để tìm các trường hợp cạnh có thứ tự quan trọng. Trừ khi trường hợp cạnh cụ thể được chỉ ra áp dụng cho tình huống của tôi, tôi chỉ yêu cầu các cột một cách hợp lý trên BẢNG TẠO của tôi. Tôi hy vọng điều này có ích.


1

Tôi hiểu ý bạn. Từ quan điểm thiết kế một bảng trông như thế này:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

tốt hơn rất nhiều so với một cái bàn trông như thế này:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

Nhưng công cụ cơ sở dữ liệu không thực sự quan tâm đến thứ tự cột logic của bạn nếu bạn phát hành một tsql như thế này:

SELECT FirstName, LastName, SSN FROM Employees

Công cụ chỉ biết nơi danh sách FirstName được lưu trữ trong đĩa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.