ในขณะที่สร้างฐานข้อมูลทดสอบสำหรับคำถามอื่นที่ฉันถามไปก่อนหน้านี้ฉันจำเกี่ยวกับคีย์หลักที่สามารถประกาศได้ NONCLUSTERED
คุณจะใช้NONCLUSTERED
คีย์หลักตรงข้ามกับCLUSTERED
คีย์หลักเมื่อใด
ขอบคุณล่วงหน้า
ในขณะที่สร้างฐานข้อมูลทดสอบสำหรับคำถามอื่นที่ฉันถามไปก่อนหน้านี้ฉันจำเกี่ยวกับคีย์หลักที่สามารถประกาศได้ NONCLUSTERED
คุณจะใช้NONCLUSTERED
คีย์หลักตรงข้ามกับCLUSTERED
คีย์หลักเมื่อใด
ขอบคุณล่วงหน้า
คำตอบ:
คำถามไม่ใช่ 'เมื่อ PK ควรเป็น NC' แต่คุณควรถามว่า 'อะไรคือคีย์ที่เหมาะสมสำหรับดัชนีคลัสเตอร์'
และคำตอบนั้นขึ้นอยู่กับว่าคุณค้นหาข้อมูลอย่างไร ดัชนีคลัสเตอร์มีข้อได้เปรียบเหนือดัชนีอื่น ๆ ทั้งหมด: เนื่องจากมีคอลัมน์ทั้งหมดอยู่เสมอจึงครอบคลุมอยู่เสมอ ดังนั้นการสืบค้นที่สามารถใช้ประโยชน์จากดัชนีคลัสเตอร์อย่างแน่นอนไม่จำเป็นต้องใช้การค้นหาเพื่อตอบสนองคอลัมน์และ / หรือเพรดิเคตที่คาดการณ์ไว้บางส่วน
ปริศนาอีกชิ้นคือดัชนีสามารถใช้งานได้อย่างไร? มีสามรูปแบบทั่วไป:
ดังนั้นหากคุณวิเคราะห์ภาระที่คาดหวังของคุณ (และแบบสอบถาม) และค้นพบว่าแบบสอบถามจำนวนมากจะใช้ดัชนีเฉพาะเนื่องจากพวกเขาใช้รูปแบบการเข้าถึงบางอย่างที่ได้รับประโยชน์จากดัชนีจึงเหมาะสมที่จะเสนอดัชนีนั้นเป็นดัชนีคลัสเตอร์
แต่อีกปัจจัยหนึ่งคือการที่สำคัญดัชนีคลัสเตอร์เป็นกุญแจสำคัญในการค้นหาที่ใช้โดยทั้งหมดดัชนีไม่มีคลัสเตอร์และดังนั้นจึงคีย์ดัชนีคลัสเตอร์กว้างสร้างผลกระเพื่อมและกว้างทั้งหมดดัชนีไม่มีคลัสเตอร์และดัชนีกว้างหมายถึงหน้ามากขึ้น I / O หน่วยความจำมากขึ้นความดีน้อยลง
ดัชนีคลัสเตอร์ที่ดีมีความเสถียรไม่เปลี่ยนแปลงระหว่างอายุการใช้งานของเอนทิตีเนื่องจากการเปลี่ยนแปลงค่าคีย์ดัชนีคลัสเตอร์หมายความว่าแถวจะต้องถูกลบและแทรกกลับ
และดัชนีกลุ่มที่ดีจะเพิ่มขึ้นตามลำดับโดยไม่สุ่ม (แต่ละค่าคีย์ที่แทรกใหม่มีขนาดใหญ่กว่าค่าก่อนหน้า) เพื่อหลีกเลี่ยงการแยกหน้าและการแตกแฟรกเมนต์ (โดยไม่ยุ่งกับFILLFACTOR
s)
ดังนั้นตอนนี้เราจึงรู้ว่าคีย์ดัชนีคลัสเตอร์ที่ดีคืออะไรคีย์หลัก (ซึ่งเป็นคุณสมบัติการสร้างแบบจำลองข้อมูลตรรกะ) ตรงกับความต้องการหรือไม่ ถ้าใช่ดังนั้นควรจะทำคลัสเตอร์ PK ถ้าไม่แสดงว่า PK ไม่ควรทำคลัสเตอร์
ในการให้ตัวอย่างพิจารณาตารางข้อเท็จจริงการขาย แต่ละรายการมี ID ที่เป็นคีย์หลัก แต่ส่วนใหญ่ของคำสั่งขอข้อมูลระหว่างวันที่และวันที่อื่นจึงคีย์ดัชนีกลุ่มที่ดีที่สุดจะขายวันที่ไม่ได้หมายเลข อีกตัวอย่างของการมีดัชนีคลัสเตอร์ที่แตกต่างจากคีย์หลักคือคีย์การเลือกที่ต่ำมากเช่น 'หมวดหมู่' หรือ 'สถานะ' ซึ่งเป็นคีย์ที่มีค่าแตกต่างกันเพียงเล็กน้อยเท่านั้น การมีคีย์ดัชนีแบบคลัสเตอร์ที่มีคีย์การเลือกระดับต่ำนี้เป็นคีย์ซ้ายสุดเช่น(state, id)
มักจะมีเหตุผลเนื่องจากช่วงการสแกนที่ค้นหารายการทั้งหมดใน 'สถานะ' โดยเฉพาะ
หมายเหตุสุดท้ายหนึ่งเกี่ยวกับความเป็นไปได้ของคีย์หลักที่ไม่ทำคลัสเตอร์เหนือฮีป (กล่าวคือไม่มีดัชนีที่ทำคลัสเตอร์เลย) นี่อาจเป็นสถานการณ์ที่ถูกต้องเหตุผลทั่วไปคือเมื่อประสิทธิภาพการแทรกจำนวนมากมีความสำคัญเนื่องจากฮีปมีปริมาณงานแทรกจำนวนมากที่ดีกว่าอย่างมากเมื่อเปรียบเทียบกับดัชนีคลัสเตอร์
(state, id)
หนึ่งคำถามเกี่ยวกับตัวอย่าง ในตัวอย่างนี้ความต้องการ "ดัชนีคลัสเตอร์ที่ดีจะเพิ่มขึ้นตามลำดับไม่สุ่ม" จะไม่เป็นเช่นนั้นใช่ไหม ดังนั้นเราสามารถพิจารณาว่าเป็นดัชนีกลุ่มที่ดีหรือไม่
เหตุผลพื้นฐานในการใช้ดัชนีแบบคลัสเตอร์มีการระบุไว้ในWikipedia :
การทำคลัสเตอร์จะเปลี่ยนแปลงบล็อกข้อมูลลงในลำดับที่แตกต่างกันเพื่อให้ตรงกับดัชนีส่งผลให้ข้อมูลแถวถูกจัดเก็บตามลำดับ ดังนั้นดัชนีคลัสเตอร์เดียวเท่านั้นที่สามารถสร้างได้ในตารางฐานข้อมูลที่กำหนด ดัชนีแบบกลุ่มสามารถเพิ่มความเร็วในการดึงข้อมูลโดยรวมได้อย่างมาก แต่โดยทั่วไปจะมีการเข้าถึงข้อมูลตามลำดับในลำดับเดียวกันหรือย้อนกลับของดัชนีคลัสเตอร์หรือเมื่อเลือกช่วงของรายการ
บอกว่าฉันมีตารางคนและคนเหล่านี้มีคอลัมน์ประเทศและคีย์หลักที่ไม่ซ้ำกัน เป็นตารางข้อมูลประชากรดังนั้นสิ่งเหล่านี้เป็นสิ่งเดียวที่ฉันสนใจ ประเทศใดและมีผู้คนที่เป็นเอกลักษณ์จำนวนเท่าใดที่เชื่อมโยงกับประเทศนั้น
ฉันมักจะเลือกที่ใดก็ได้หรือเรียงตามคอลัมน์ประเทศ; ดัชนีคลัสเตอร์ในคีย์หลักไม่ได้ทำอะไรให้ฉันดีฉันไม่ได้เข้าถึงข้อมูลนี้โดย PK ฉันกำลังเข้าถึงโดยคอลัมน์อื่นนี้ เนื่องจากฉันสามารถมีดัชนีคลัสเตอร์เดียวได้บนโต๊ะการประกาศ PK ของฉันเนื่องจาก Clustered จะป้องกันไม่ให้ฉันใช้ดัชนีแบบกลุ่มในประเทศ
นอกจากนี้ต่อไปนี้เป็นบทความที่ดีเกี่ยวกับดัชนีที่ไม่ได้ทำคลัสเตอร์แบบไม่รวมกลุ่มกลายเป็นดัชนีแบบกลุ่มทำให้เกิดปัญหาประสิทธิภาพการแทรกใน SQL Server 6.5 (ซึ่งอย่างน้อยหวังว่าจะไม่เกี่ยวข้องกับพวกเราส่วนใหญ่ที่นี่)
หากคุณใส่ดัชนีแบบกลุ่มในคอลัมน์ตัวตนเม็ดมีดทั้งหมดของคุณจะเกิดขึ้นในหน้าสุดท้ายของตาราง - และหน้านั้นจะถูกล็อคตามระยะเวลาของแต่ละ IDENTITY ไม่มีเรื่องใหญ่ ... เว้นแต่คุณจะมีคน 5,000 คนที่ต้องการหน้าสุดท้าย จากนั้นคุณมีข้อโต้แย้งมากมายสำหรับหน้านั้น
โปรดทราบว่านี่ไม่ใช่กรณีในรุ่นที่ใหม่กว่า
ถ้าคีย์หลักของคุณคือของให้แน่ใจว่าจะระบุว่ามันเป็นUNIQUEIDENTIFIER
NONCLUSTERED
หากคุณทำให้มันเป็นกลุ่มทุกส่วนแทรกจะต้องทำการสับเรคคอร์ดจำนวนมากเพื่อแทรกแถวใหม่ในตำแหน่งที่ถูกต้อง ประสิทธิภาพของรถถังนี้
UNIQUEIDENTIFIER
ชนิดของการเรียงลำดับมีอยู่ด้วยและมีความน่าจะเป็นเหมือนกันในการสร้างคีย์ที่ไม่ซ้ำกันแม้ว่ามันจะยังคงทนทุกข์ทรมานจากขนาด 128
ตัวอย่างทั่วไป:
Customer
ตารางที่มีCustomerID
ฐานะCLUSTERED PRIMARY KEY
OrderID (PK), CustomerID, OrderDate
และคอลัมน์อื่น ๆOrderPositions
กับ OrderPositionID (PK), OrderId, ProductID, Amount, Price ...
แน่นอน "มันขึ้นอยู่กับ" คือ - เกือบทุกครั้ง - คำตอบที่ถูกต้อง แต่แอปพลิเคชันส่วนใหญ่ (ไม่ใช่รายงาน BI) จะทำงานกับลูกค้า (เช่นคุณเข้าสู่ระบบในฐานะลูกค้า 278 เข้าสู่เว็บไซต์และคลิกที่ "คำสั่งซื้อของฉัน" หรือ เสมียนแสดงรายการคำสั่งซื้อทั้งหมดสำหรับลูกค้า 4569 หรือขั้นตอนการออกใบแจ้งหนี้ของคุณจะสรุปคำสั่งซื้อทั้งหมดสำหรับลูกค้า 137)
OrderID
ในกรณีนี้ก็จะทำให้รู้สึกไม่มากที่จะจัดกลุ่มตารางโดย ใช่คุณจะมีข้อความค้นหาSELECT ... WHERE OrderId = ?
เพื่อแสดงรายละเอียดการสั่งซื้อ แต่โดยปกติจะเป็นการค้นหาดัชนีสั้น ๆ และราคาถูก (3 ครั้ง)
ในทางตรงกันข้ามถ้าคุณจะคลัสเตอร์ของคุณOrder
ตารางโดยมันจะไม่ต้องทำการค้นหาที่สำคัญหลายครั้งที่คุณสอบถามตารางสำหรับCustomerID
CustomerId = ?
CLUSTERED INDEX
ควรจะเสมอUNIQUE
มิฉะนั้น SQL Server จะเพิ่มที่มองไม่เห็น (= ใช้ไม่ได้) คอลัมน์ INT UNIQUIFIER
เพื่อให้แน่ใจว่า uniquiness - และมันจะทำให้รู้สึกมากขึ้นเพื่อเพิ่มจริงข้อมูล (งาน) แล้วบางสุ่ม (ขึ้นอยู่กับคำสั่งแทรก) สิ่ง
เนื่องจากลูกค้าจะ (หวังว่า) จะสั่งซื้อมากกว่าหนึ่งคำสั่งซื้อเราจะต้องเพิ่มอย่างใดอย่างหนึ่งOrderID
หรือ (ถ้าคุณมักจะเรียงลำดับนี้) ที่OrderDate
(ถ้ามันเป็นวันที่และเวลา - มิฉะนั้นลูกค้าจะถูก จำกัด เพียงหนึ่งคำสั่งต่อวัน) CLUSTERED INDEX
และจบลงด้วย:
CREATE UNIQUE CLUSTERED INDEX IX_Orders_UQ on Orders (CustomerID, OrderID)
กฎเดียวกันนี้ใช้กับOrderPositions
ตาราง มักจะมีคำสั่งส่วนใหญ่จะแสดงรายการทุกตำแหน่งสำหรับการสั่งซื้อที่เฉพาะเจาะจงเพื่อคุณควรสร้าง PK ที่มีOrderPositionID
ฐานะNONCLUSTERED
และบนUNIQUE CLUSTERED INDEX
OrderId, OrderPositionID
BTW: มันถูกต้องว่าCustomer
ตารางนั้นมีการรวมกลุ่มโดย PK (the CustomerID
, เพราะมันเป็น "Top-Level-Table" และจะ - ในแอปพลิเคชันทั่วไป - ส่วนใหญ่จะถูกสอบถามโดย CustomerID
ตารางการค้นหาบริสุทธิ์เป็นเช่นGenders
หรือInvoiceTypes
หรือPaymentType
เป็นอีกตัวอย่างหนึ่งของตารางที่ควรจะคลัสเตอร์โดย PK มัน (เพราะคุณมักจะเข้าร่วมพวกเขาในGenderId
, InvoiceTypeId
หรือPaymentTypeId
)
เมื่อดัชนีกลุ่มถือว่ามีประโยชน์ต่อระบบโดยรวมมากกว่า PK แบบคลัสเตอร์โดยใช้การวัดประสิทธิภาพ สามารถมีดัชนีคลัสเตอร์ได้หนึ่งรายการเท่านั้นในตาราง
ตัวอย่างการวัดประสิทธิภาพคือเวลาแบบสอบถามเดียว (ความเร็ว), การรวมเวลาแบบสอบถามทั้งหมดกับตาราง (ประสิทธิภาพ) และต้องเพิ่มคอลัมน์หลายคอลัมน์ลงใน a ไปยังดัชนีที่ไม่ใช่คลัสเตอร์ขนาดใหญ่มากเพื่อให้ได้ประสิทธิภาพคล้ายกับคลัสเตอร์ (ขนาด )
สิ่งนี้สามารถเกิดขึ้นได้โดยทั่วไปเมื่อมีการดึงข้อมูลโดยใช้ดัชนีที่ไม่ซ้ำกันมีค่า Null (ไม่อนุญาตใน PK) หรือมีการเพิ่ม PK ด้วยเหตุผลรอง (เช่นการจำลองแบบหรือการระบุบันทึกหลักฐานการตรวจสอบ)