ลำดับของคอลัมน์ในคำจำกัดความของตารางมีความสำคัญหรือไม่


35

เมื่อกำหนดตารางการเรียงลำดับคอลัมน์ในกลุ่มเชิงตรรกะและกลุ่มจะเป็นประโยชน์ การเรียงลำดับแบบลอจิคัลของคอลัมน์ในตารางบ่งบอกถึงความหมายของผู้พัฒนาและเป็นองค์ประกอบของสไตล์ที่ดี

นั่นชัดเจน

อย่างไรก็ตามสิ่งที่ไม่ชัดเจนคือว่าการเรียงลำดับเชิงตรรกะของคอลัมน์ในตารางมีผลกระทบต่อการจัดเรียงทางกายภาพที่ชั้นการจัดเก็บหรือไม่หรือมีผลกระทบอื่น ๆ ที่อาจสนใจ

นอกเหนือจากผลกระทบต่อสไตล์การเรียงลำดับของคอลัมน์มีความสำคัญหรือไม่

มีคำถามเกี่ยวกับ Stack Overflowเกี่ยวกับเรื่องนี้ แต่ไม่มีคำตอบที่เชื่อถือได้

คำตอบ:


23

การเรียงลำดับแบบลอจิคัลของคอลัมน์ในตารางมีผลกระทบกับลำดับฟิสิคัลที่เลเยอร์การจัดเก็บหรือไม่? ใช่.

ไม่ว่ามันจะสำคัญหรือไม่ก็เป็นอีกเรื่องที่ฉันยังไม่สามารถตอบได้

ในทำนองเดียวกันกับที่อธิบายไว้ในบทความที่เชื่อมโยงบ่อยๆจาก Paul Randal เกี่ยวกับกายวิภาคของบันทึกลองดูที่ตารางคอลัมน์สองคอลัมน์อย่างง่ายกับ 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 ':

Memory Dump @0x000000000D25A060

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

และเพราะให้เปิดหน้าอกRowStructure.mdfด้วยโปรแกรมแก้ไข hex และยืนยันสตริง '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... 

อีกครั้งสำหรับ giggles ให้ตรวจสอบ hex dump ของไฟล์ข้อมูล:

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)
Martin Smith

1
คำสั่งคอลัมน์อาจมีความหมายในกรณีมุมที่หายาก ตัวอย่างเช่นหากคุณมีตารางที่มี 3 คอลัมน์ A, B และ C แต่ละไบต์จะยาว 3kb หน้าเซิร์ฟเวอร์ SQL มีขนาด 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 แสดงให้เห็นว่าฉันคิดว่าดีกว่า
Ronen Ariely

@RonenAriely เป็นตัวอย่างที่น่าสนใจ แต่มันค่อนข้างมีการวางแผนในบริบทของคำถามเดิม คุณแสดงให้เห็นว่าการเรียงลำดับคอลัมน์มีผลกระทบอย่างไรในเวลาต่อมาคุณวางคอลัมน์ ฉันไม่คิดว่าฉันเคยออกแบบตารางที่มีการคาดการณ์ล่วงหน้าว่าจะวางคอลัมน์ใด
Mark Storey-Smith

สวัสดี @ MarkStorey-Smith (1) ในฐานะสถาปนิกฉันอธิบายอยู่เสมอว่าความแตกต่างระหว่างการออกแบบที่ดีและการออกแบบที่ยอดเยี่ยมคือการออกแบบที่ดีนั้นตอบสนองความต้องการในปัจจุบันในขณะที่การออกแบบที่ยอดเยี่ยมนั้นตอบสนองความต้องการในอนาคตที่ยังไม่เป็นที่ทราบ (2) คำตอบของคำถามคือใช่จริง การดำเนินการตามคำตอบนั้นขึ้นอยู่กับ OP และเราแต่ละคน นี่อยู่นอกขอบเขตของการสนทนา แต่เราสามารถเปิดหัวข้อนี้เพื่อการสนทนา แต่ไม่ได้อยู่ที่ตระกูลฟอรัมสแต็คเนื่องจากอินเตอร์เฟสไม่อนุญาตให้มีการสนทนาจริง แต่เพียงเพิ่มข้อความสั้น ๆ บรรทัดเดียวในการตอบกลับ
Ronen Ariely

7

หากคุณไม่ได้กำหนดดัชนีคลัสเตอร์คุณจะได้รับตารางฮีป สำหรับตารางฮีปคุณจะทำการสแกนทุกครั้งเมื่ออ่านข้อมูลและจะอ่านทั้งแถวโดยแสดงลำดับของคอลัมน์เป็นจุดที่สงสัย

ทันทีที่คุณกำหนดดัชนีคลัสเตอร์ข้อมูลจะถูกจัดเรียงทางกายภาพใหม่เพื่อให้สอดคล้องกับลำดับทางกายภาพของคอลัมน์ตามที่คุณระบุ - และ ณ จุดนี้ลำดับทางกายภาพจะกลายเป็นสิ่งสำคัญ ลำดับทางกายภาพคือสิ่งที่กำหนดคุณสมบัติของผู้ปฏิบัติงานที่กำลังมองหาตามภาคแสดงที่คุณใช้

แม้ว่าฉันจะจำการอ่านไม่ได้ทุกที่ แต่ฉันคิดว่า SQL Server ไม่รับประกันลำดับทางกายภาพของคอลัมน์สำหรับฮีปในขณะที่มันจะรับประกันสำหรับดัชนี เพื่อตอบคำถามของคุณไม่ลำดับของคอลัมน์ในคำจำกัดความไม่ควรสำคัญเนื่องจากจะไม่สำคัญเมื่ออ่านข้อมูล (โปรดทราบว่าสิ่งนี้มีไว้สำหรับกองเท่านั้น - ดัชนีเป็นเรื่องที่แตกต่างกัน)

อัปเดต
จริง ๆ แล้วคุณถามคำถามสองข้อ - "การเรียงลำดับแบบลอจิคัลของคอลัมน์ในตารางมีผลกระทบกับการจัดเรียงแบบกายภาพที่เลเยอร์การจัดเก็บ" หรือไม่ ลำดับตรรกะตามที่กำหนดโดยข้อมูลเมตาไม่จำเป็นต้องอยู่ในลำดับเดียวกับกายภาพ สิ่งที่ฉันรวบรวมคุณกำลังมองหาคำตอบคือว่าลำดับเชิงตรรกะใน CREATE TABLE ส่งผลในลำดับทางกายภาพเดียวกันกับการสร้าง - ซึ่งฉันไม่ทราบสำหรับกอง - แม้ว่ากับข้อแม้ข้างต้น


2

จากสิ่งที่ฉันได้เห็นและอ่านการเรียงลำดับของคอลัมน์ใน SQL Server นั้นไม่แตกต่างกัน เอ็นจิ้นการจัดเก็บวางคอลัมน์ในแถวโดยไม่คำนึงถึงวิธีที่ระบุในคำสั่ง CREATE TABLE ที่ถูกกล่าวว่าฉันแน่ใจว่ามีบางกรณีที่แยกโดดเดี่ยวมากที่มันเป็นเรื่องสำคัญ แต่ฉันคิดว่าคุณจะมีเวลายากที่จะได้รับคำตอบที่ชัดเจนเกี่ยวกับสิ่งเหล่านี้ ผลงานของ Paul Randal " Inside The Storage Engine"หมวดหมู่บล็อกของโพสต์เป็นแหล่งข้อมูลที่ดีที่สุดสำหรับรายละเอียดทั้งหมดเกี่ยวกับวิธีการทำงานของเครื่องมือจัดเก็บข้อมูลที่ฉันรู้จักฉันคิดว่าคุณจะต้องศึกษาวิธีการต่างๆทั้งหมดที่การจัดเก็บและเมทริกซ์ทำงานกับกรณีการใช้งานทั้งหมด เพื่อค้นหาเคสขอบที่คำสั่งซื้อจะมีความสำคัญเว้นแต่กรณี edge เฉพาะจะชี้ให้เห็นว่าใช้กับสถานการณ์ของฉันฉันเพียงแค่สั่งคอลัมน์ตามหลักตรรกะบน CREATE TABLE ของฉันฉันหวังว่านี่จะช่วยได้


1

ฉันได้สิ่งที่คุณหมายถึง จากมุมมองการออกแบบตารางที่มีลักษณะเช่นนี้:

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

ดีกว่าตารางที่มีลักษณะดังนี้:

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

แต่เอ็นจิ้นฐานข้อมูลไม่สนใจลำดับคอลัมน์แบบลอจิคัลของคุณจริงๆถ้าคุณออก tsql ดังนี้:

SELECT FirstName, LastName, SSN FROM Employees

เอ็นจิ้นเพิ่งรู้ว่ารายการของ FirstName ถูกเก็บไว้ในดิสก์อย่างไร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.