การเลือกดัชนีแบบกลุ่ม - PK หรือ FK?


11

ฉันมีตารางSQL Server 2014ที่มีลักษณะดังต่อไปนี้:

OrderId     int           not null IDENTITY --this is the primary key column
OrderDate   datetime2     not null
CustomerId  int           not null
Description nvarchar(255) null

บางคนในทีมของฉันแนะนำว่าควรทำดัชนีคลัสเตอร์OrderIdแต่ฉันคิดว่าCustomerId+ OrderIdจะเป็นตัวเลือกที่ดีกว่าด้วยเหตุผลต่อไปนี้:

  • แบบสอบถามเกือบทั้งหมดจะมองWHERE CustomerId = @paramไม่ใช่OrderId
  • CustomerIdเป็น foreign key ไปยังCustomerตารางดังนั้นการมีดัชนีคลัสเตอร์ที่CustomerIdควรเพิ่มความเร็วในการรวม
  • แม้ว่าCustomerIdจะไม่ซ้ำกันการมีOrderIdคอลัมน์เพิ่มเติมที่ระบุไว้ในดัชนีจะทำให้มั่นใจได้ว่าไม่ซ้ำกัน (เราสามารถใช้UNIQUEคำหลักเมื่อสร้างดัชนีคลัสเตอร์ในคอลัมน์ 2 คอลัมน์เหล่านั้นเพื่อหลีกเลี่ยงค่าใช้จ่ายที่ไม่มีเอกลักษณ์)
  • เมื่อแทรกข้อมูลแล้วCustomerIdและOrderIdไม่เปลี่ยนแปลงดังนั้นแถวเหล่านี้จะไม่ย้ายไปหลังจากการเขียนครั้งแรก
  • การเข้าถึงข้อมูลเกิดขึ้นผ่านทาง ORM ที่ร้องขอคอลัมน์ทั้งหมดตามค่าเริ่มต้นดังนั้นเมื่อมีการค้นหาตามCustomerIdมาดัชนีดัชนีคลัสเตอร์จะสามารถให้คอลัมน์ทั้งหมดโดยไม่ต้องทำงานเพิ่มเติมใด ๆ

ที่ไม่CustomerIdและOrderIdเสียงเช่นวิธีการเลือกที่ดีที่สุดที่กำหนดข้างต้น หรือเป็นOrderIdของตัวเองดีกว่าเพราะมันเป็นคอลัมน์เดียวที่รับประกันความโดดเด่นด้วยตัวเอง?

ขณะนี้ตารางมีดัชนีคลัสเตอร์บนOrderIdและดัชนีที่CustomerIdไม่ได้ทำคลัสเตอร์แต่มันไม่ครอบคลุมดังนั้นเนื่องจากเราใช้ ORM และมีการร้องขอคอลัมน์ทั้งหมดจึงเป็นงานพิเศษเพื่อดึงข้อมูลออกมา ดังนั้นเมื่อโพสต์นี้ฉันพยายามพิจารณาปรับปรุงประสิทธิภาพด้วย CI ที่ดีขึ้น

กิจกรรมในฐานข้อมูลของเรามีประมาณ 85% การอ่านและการเขียน 15%

คำตอบ:


5

ชุมชนวิกิพีเดียคำตอบ :

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

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

OrderIDหรือOrderDateอาจดีที่สุดสำหรับคอลัมน์ที่สองขึ้นอยู่กับการสืบค้นที่สำคัญที่สุดของคุณ

ตัวอย่างเช่นถ้าลูกค้าดูรายการตามลำดับของการสั่งซื้อที่ผ่านมาหลังจากที่เข้าสู่เว็บไซต์OrderDateORDER BY OrderDate DESCควรจะเป็นต่อไปเพื่อเพิ่มประสิทธิภาพ

หากคุณเลือกOrderIDเป็นดัชนีที่มีดัชนีที่ไม่ใช่คลัสเตอร์ในCustomerIDคุณจะยังคงได้รับการแยกและการแยกส่วนเพียงในดัชนีที่ไม่ใช่คลัสเตอร์


3

ถ้าตารางนี้จะหนักเขียนอย่างเข้มข้น (เช่นอื่น ๆ อีกมากมายINSERTงบจะเกิดขึ้นมากกว่าSELECTงบกับมัน) ผมจะไม่เห็นด้วยกับคำตอบของวิกิพีเดีย

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

ถ้าคุณรู้สึกว่า CustomerID ควรเป็นคอลัมน์นำของดัชนีคอมโพสิตคลัสเตอร์คุณสามารถลดผลกระทบของการแบ่งหน้ากลางได้โดยปรับFILLFACTORดัชนีทั้งหมดสำหรับตารางนี้ สิ่งนี้จะลดจำนวนการแบ่งกลางหน้าด้วยการเพิ่มขนาดของตาราง / ดัชนี หากคุณต้องการไปเส้นทางนี้ฉันขอแนะนำให้ทดสอบด้วยค่า 80 และลดลงหากการวิเคราะห์พบว่าการแยกกลางหน้ายังคงเป็นการฆ่าประสิทธิภาพ

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

กิจกรรมในฐานข้อมูลของเรามีประมาณ 85% การอ่านและการเขียน 15%

CustomerID+ OrderID(และการระบุสารเติมเพื่อให้การเจริญเติบโตโดยไม่แยก) น่าจะดีกว่าถ้าการประเมินนั้นเป็นจริง เพียงตรวจสอบให้แน่ใจว่าการประเมินนั้นถูกต้อง ทดสอบทดสอบทดสอบ


1
โปรดทราบว่าการแทรกคำสั่งซื้อสำหรับลูกค้าสุดท้าย (หรือเฉพาะ) ในหน้านั้นไม่ใช่ "การแบ่งหน้ากลาง" ดังนั้นหากคำสั่งซื้อต่อลูกค้าสูงหรือความกว้างของแถวมีขนาดใหญ่ดังนั้นการแทรกคำสั่งซื้อที่น้อยลงจะต้องใช้ "การแบ่งกลางหน้า"
David Browne - Microsoft
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.