คลัสเตอร์เทียบกับไม่ใช่คลัสเตอร์


98

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

เรามีโต๊ะที่มี 'คำสั่งศาล' สำหรับผู้คน เมื่อฉันสร้างตาราง (ชื่อ: CourtOrder) ฉันสร้างมันดังนี้:

CREATE TABLE dbo.CourtOrder
(
  CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
  PersonId INT NOT NULL,
  + around 20 other fields of different types.
)

จากนั้นฉันใช้ดัชนีที่ไม่ใช่คลัสเตอร์กับคีย์หลัก (เพื่อประสิทธิภาพ) เหตุผลของฉันคือมันเป็นฟิลด์ที่ไม่ซ้ำกัน (คีย์หลัก) และควรจัดทำดัชนีเพื่อจุดประสงค์ในการเลือกเป็นหลักเนื่องจากเรามักจะSelect from table where primary key = ...

จากนั้นฉันใช้ดัชนี CLUSTERED กับ PersonId เหตุผลก็คือเพื่อจัดกลุ่มคำสั่งซื้อสำหรับบุคคลใดบุคคลหนึ่งทางร่างกายเนื่องจากงานส่วนใหญ่ได้รับคำสั่งจากบุคคล ดังนั้น,select from mytable where personId = ...

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

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

พวกเขากล่าวว่าเนื่องจากเรารวมกลุ่ม personId SQL Server จึงต้องจัดเรียงข้อมูลใหม่เมื่อเราแทรกหรือเปลี่ยนแปลง PersonId

ดังนั้นฉันจึงถามว่าทำไม SQL ถึงมีแนวคิดของ CLUSTERED INDEX ถ้ามันช้าขนาดนี้? ช้าอย่างที่พูดหรือเปล่า ฉันควรตั้งค่าดัชนีของฉันอย่างไรเพื่อให้ได้ประสิทธิภาพสูงสุด ฉันคิดว่า SELECT ถูกใช้มากกว่า INSERT ... แต่พวกเขาบอกว่าเรากำลังมีปัญหาในการล็อค INSERTS ...

หวังว่าจะมีคนช่วยฉันได้


คำตอบ:


117

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

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

สิ่งเดียวที่ฉันขอแนะนำคือไม่ใช้CourtOrderIdคอลัมน์คีย์ตัวแทน (ของคุณ) เป็นคีย์หลัก แต่ให้ใช้คีย์หลักแบบผสมของPersonIdคอลัมน์หรือชุดคอลัมน์อื่นที่ไม่ซ้ำกัน หากเป็นไปไม่ได้ (หรือใช้ไม่ได้จริง) ให้ใส่ดัชนีคลัสเตอร์CourtOrderIdไว้


ขอบคุณอดัม แล้วดัชนีคลัสเตอร์จะมีประโยชน์เมื่อใด ฉันคิดว่าประโยชน์ของการทำดัชนีคลัสเตอร์คือการจัดกลุ่มข้อมูลในบางครั้งตัวอย่างเช่นการสืบค้นส่วนใหญ่อยู่ใน PersonID ... ดังนั้นข้อมูลจะถูกจัดกลุ่ม
Craig

3
มันเป็นเรื่องที่ไม่ได้PersonIdเรียงร่างกาย มีการเรียงลำดับตามเหตุผลPersonIdความแตกต่างระหว่างลำดับตรรกะและทางกายภาพคือระดับของการกระจายตัวทางตรรกะ
Martin Smith

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

1
@CyberSluethOmega: ไม่รู้; คำถามของคุณไม่มีข้อมูลเพียงพอให้ฉันตัดสินใจ ฉันต้องการดัชนีคลัสเตอร์ในชุดคอลัมน์ที่มักจะเพิ่มหรือลบแถวนอกเหนือจากท้ายตารางหรือไม่ ไม่ แต่ฉันไม่แน่ใจจริงๆว่าทำไมคุณถึงถามอย่างนั้นหรือทำไมถึงโหวตลด
Adam Robinson

1
@CyberSluethOmega: อินเทอร์เน็ตสามารถแสดงความคิดเห็นในเชิงป้องกันหรือเย็นชาเมื่อพวกเขาไม่ได้ตั้งใจอย่างนั้น คุณอ้างว่าฉันบอกว่าฉันไม่ทราบว่าจะสร้างดัชนีคลัสเตอร์เป็นอย่างอื่นนอกเหนือจากคีย์หลักในความเป็นจริงฉันไม่ได้พูดแบบนั้น ในความเป็นจริงสิ่งที่ฉันบอกว่า "นี่คือความผิดปกติ ... แต่ไม่เคยได้ยินจาก" ซึ่งหมายความว่าผมไม่ทราบว่ากรณีที่นี้จะทำ
Adam Robinson

14

ฉันไม่ได้เป็นผู้เชี่ยวชาญด้าน SQL ... ดังนั้นให้ถือเป็นมุมมองของนักพัฒนามากกว่ามุมมอง DBA ..

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

ฉันสมมติว่า PersonId ของคุณจะไม่เปลี่ยนแปลงดังนั้น Updates จึงไม่เข้ามาเล่นที่นี่ แต่พิจารณาภาพรวมของแถวสองสามแถวด้วย PersonId เป็น 1 2 3 3 4 5 6 7 8 8

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

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

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

ไม่ว่าในกรณีใดขอให้โชคดี!


5

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

จากแนวทางการออกแบบดัชนีคลัสเตอร์ของ MSDN ควรเลือกคีย์ตามเกณฑ์ต่อไปนี้

  1. สามารถใช้สำหรับแบบสอบถามที่ใช้บ่อย
  2. ให้ความเป็นเอกลักษณ์สูง
  3. สามารถใช้ในการสืบค้นช่วง

คุณคอลัมน์ตรงตามCourtOrderID 2คุณPersonIdมีคุณสมบัติตรงตามและ1 3เนื่องจากแถวส่วนใหญ่จะลงท้ายด้วยการuniqueifierเพิ่มอย่างไรก็ตามคุณอาจเพียงแค่ประกาศว่าไม่ซ้ำกันและใช้PersonId,CourtOrderIDเพราะจะมีความกว้างเท่ากัน แต่มีประโยชน์มากกว่าเนื่องจากคีย์ดัชนีคลัสเตอร์จะถูกเพิ่มลงใน NCI ทั้งหมดเป็นตัวระบุตำแหน่งและสิ่งนี้จะช่วยให้ เพื่อให้ครอบคลุมคำถามเพิ่มเติม

ปัญหาหลักในการใช้PersonId,CourtOrderIDเป็น CI คือการแยกส่วนเชิงตรรกะมีแนวโน้มที่จะเกิดขึ้น (และโดยเฉพาะอย่างยิ่งจะส่งผลต่อการสืบค้นช่วงที่คุณพยายามช่วย) ดังนั้นคุณจะต้องตรวจสอบปัจจัยการเติมและระดับการแยกส่วนและทำการบำรุงรักษาดัชนีบ่อยขึ้น


3

มีคำอธิบายในลิงค์ต่อไปนี้: https://msdn.microsoft.com/en-us/ms190457.aspx

คลัสเตอร์

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

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

ไม่เป็นคลัสเตอร์

  • ดัชนีที่ไม่เป็นคลัสเตอร์มีโครงสร้างที่แยกจากแถวข้อมูล nonclustered ดัชนีคontains ค่าคีย์ดัชนี nonclustered และแต่ละรายการค่าคีย์มีตัวชี้ไปยังแถวข้อมูลที่มีค่าสำคัญ

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

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


-3

ฐานข้อมูลบางตัวที่มีการเลือกที่น่ารังเกียจบางส่วนเข้าร่วมในกระบวนงานที่เก็บไว้ - ความแตกต่างเท่านั้นคือดัชนี

INDEXES - คลัสเตอร์เทียบกับไม่เป็นคลัสเตอร์

  891 rows
  10 sec
  NONCLUSTERED 

  OR

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