เหตุใดจึงใช้เวลานานกว่าในการสร้างดัชนีหลังจากขนาดคอลัมน์เพิ่มขึ้น


18

ผู้ขายของเราเปลี่ยนความกว้างของคอลัมน์ในเกือบทุกคอลัมน์ในฐานข้อมูลทั้งหมด ฐานข้อมูลอยู่ที่ประมาณ 7TB, 9000+ ตาราง เรากำลังพยายามสร้างดัชนีบนตารางที่มี 5.5 พันล้านแถว ก่อนการอัพเกรดของผู้ขายเราสามารถสร้างดัชนีได้ภายใน 2 ชั่วโมง ตอนนี้ต้องใช้เวลาหลายวัน สิ่งที่พวกเขาทำคือเพิ่มขนาด varchar (xx) เป็น varchar (256) ดังนั้นคอลัมน์ส่วนใหญ่เคยเป็น varchar (18) หรือ varchar (75) เป็นต้น

อย่างไรก็ตามคีย์หลักประกอบด้วย 6 คอลัมน์ที่มีความกว้างรวมกันคือ 126 ตัวอักษร หลังจากอัปเกรดแล้วคีย์หลักคือ 1283 ตัวอักษรซึ่งละเมิดข้อ จำกัด ของเซิร์ฟเวอร์ SQL 900 ตัวอักษร ความกว้างคอลัมน์ของตารางทั้งหมดเพิ่มขึ้นจากการนับรวม varchar รวม 1049 ถึงการรวม varchar รวม 4009

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

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

ดัชนีที่เราพยายามสร้างนั้นไม่เป็นคลัสเตอร์เนื่องจาก pk เป็นดัชนีที่ทำคลัสเตอร์ หลังจากพยายามสร้างดัชนีหลายครั้งเราก็เลิกกัน ฉันคิดว่ามันใช้เวลา 4 หรือ 5 วันโดยไม่เสร็จ

ฉันลองสิ่งนี้ในสภาพแวดล้อมที่ไม่ได้ใช้งานจริงโดยถ่ายภาพรวมระบบไฟล์และนำฐานข้อมูลขึ้นบนเซิร์ฟเวอร์ที่เงียบกว่า

คำตอบ:


12

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

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

สคริปต์ Repro

ฉันสร้างสคริปต์เต็มรูปแบบที่สร้างชุดข้อมูลปลอมซึ่งการสร้างดัชนีใช้เวลาประมาณ 10 เท่าในเครื่องของฉันสำหรับVARCHAR(256)รุ่น ข้อมูลที่ใช้เป็นสิ่งเดียวกัน แต่ตารางแรกใช้ความยาวสูงสุดที่แท้จริงของ18, 75, 9, 15, 123และ5ขณะที่คอลัมน์ทั้งหมดใช้ความยาวสูงสุด256ในตารางที่สอง


ป้อนรหัสต้นฉบับ

ที่นี่เราเห็นว่าการสืบค้นดั้งเดิมเสร็จสมบูรณ์ในเวลาประมาณ 20 วินาทีและการอ่านแบบโลจิคัลจะเท่ากับขนาดตาราง~1.5GB(195K Pages, 8K ต่อหน้า)

-- CPU time = 37674 ms,  elapsed time = 19206 ms.
-- Table 'testVarchar'. Scan count 9, logical reads 194490, physical reads 0
CREATE CLUSTERED INDEX IX_testVarchar
ON dbo.testVarchar (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO


ป้อนตาราง VARCHAR (256)

สำหรับVARCHAR(256)ตารางเราจะเห็นว่าเวลาที่ผ่านไปนั้นเพิ่มขึ้นอย่างมาก

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

-- CPU time = 33212 ms,  elapsed time = 263134 ms.
-- Table 'testVarchar256'. Scan count 9, logical reads 194491
CREATE CLUSTERED INDEX IX_testVarchar256
ON dbo.testVarchar256 (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO


I / O และรอสถานะ: ดั้งเดิม

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

เราสามารถเห็นได้ว่าดิสก์หมุนวนของฉันอยู่ระหว่าง "ไม่ดี" และ "แย่มาก" ตามที่ Paul Randal :)

ป้อนคำอธิบายรูปภาพที่นี่


I / O และรอสถานะ: VARCHAR (256)

สำหรับVARCHAR(256)เวอร์ชั่น I / O และการรอสถิติดูต่างออกไปอย่างสิ้นเชิง! ที่นี่เราเห็นการเพิ่มขึ้นอย่างมากของ I / O ในไฟล์ข้อมูล ( ROWS) และเวลาที่แผงขายทำให้พอลแรนดัลพูดง่าย ๆ ว่า "WOW!"

มันไม่น่าแปลกใจที่ # 1 IO_COMPLETIONชนิดการรออยู่ในขณะนี้ แต่ทำไม I / O ถึงถูกสร้างขึ้นมาก?

ป้อนคำอธิบายรูปภาพที่นี่


แผนแบบสอบถามจริง: VARCHAR (256)

จากแผนแบบสอบถามเราจะเห็นว่าSortผู้ประกอบการมีการรั่วไหลซ้ำ (5 ระดับลึก!) ในVARCHAR(256)รุ่นของแบบสอบถาม (ไม่มีการรั่วไหลในทุกเวอร์ชั่น)

ป้อนคำอธิบายรูปภาพที่นี่


ความคืบหน้าการสืบค้นสด: VARCHAR (256)

เราสามารถใช้ sys.dm_exec_query_profiles เพื่อดูความคืบหน้าของแบบสอบถามที่อาศัยอยู่ใน SQL 2014+ ในเวอร์ชั่นดั้งเดิมทั้งหมดTable ScanและSortประมวลผลโดยไม่มีการรั่วไหลใด ๆ ( spill_page_countยังคงอยู่0ตลอด)

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

ป้อนคำอธิบายรูปภาพที่นี่

หากฉันขุดเข้าไปในแต่ละเธรดแต่ละรายการฉันเห็นว่า 2 เธรดเสร็จสิ้นการเรียงลำดับภายในเวลาประมาณ 5 วินาที (โดยรวม @ 20 วินาทีหลังจากใช้เวลา 15 วินาทีในการสแกนตาราง) หากเธรดทั้งหมดดำเนินการด้วยอัตรานี้การVARCHAR(256)สร้างดัชนีจะเสร็จสมบูรณ์ในเวลาประมาณเดียวกับตารางดั้งเดิม

อย่างไรก็ตาม 6 เธรดที่เหลือจะดำเนินการในอัตราที่ช้ากว่ามาก นี่อาจเป็นเพราะวิธีการจัดสรรหน่วยความจำและวิธีการที่เธรดถูกจัดขึ้นโดย I / O เนื่องจากเป็นข้อมูลที่หก ฉันไม่รู้แน่นอน

ป้อนคำอธิบายรูปภาพที่นี่


คุณทำอะไรได้บ้าง?

มีหลายสิ่งที่คุณอาจพิจารณาลอง:

  • ทำงานร่วมกับผู้ขายเพื่อย้อนกลับไปเป็นเวอร์ชันก่อนหน้า หากไม่สามารถทำได้ให้ผู้ขายที่คุณไม่พอใจกับการเปลี่ยนแปลงนี้เพื่อให้พวกเขาสามารถพิจารณาคืนค่าในการวางจำหน่ายในอนาคต
  • เมื่อเพิ่มดัชนีของคุณให้พิจารณาการใช้โดยOPTION (MAXDOP X)ที่Xจำนวนต่ำกว่าการตั้งค่าระดับเซิร์ฟเวอร์ปัจจุบันของคุณ เมื่อฉันใช้OPTION (MAXDOP 2)กับชุดข้อมูลเฉพาะนี้บนเครื่องของฉันVARCHAR(256)เวอร์ชันนั้นเสร็จสมบูรณ์ใน25 seconds(เปรียบเทียบกับ 3-4 นาทีกับ 8 เธรด!) มีความเป็นไปได้ว่าพฤติกรรมการหกล้นนั้นทวีความรุนแรงมากขึ้น
  • หากการลงทุนฮาร์ดแวร์เพิ่มเติมเป็นไปได้ให้ใส่โปรไฟล์ I / O (คอขวดที่เป็นไปได้) ไว้ในระบบของคุณและพิจารณาใช้ SSD เพื่อลดเวลาแฝงของ I / O ที่เกิดจากการรั่วไหล


อ่านเพิ่มเติม

Paul White มีการโพสต์บล็อกที่ดีเกี่ยวกับการเรียงลำดับของ SQL Serverที่อาจเป็นที่สนใจ มันพูดคุยเล็กน้อยเกี่ยวกับการหก, การเอียงของเกลียวและการจัดสรรหน่วยความจำสำหรับการเรียงลำดับแบบขนาน


11

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

ทดสอบสคริปต์จาก Geoff (เฉพาะแถว 100k เท่านั้น) ฉันเห็นความแตกต่างในขนาดแถวโดยประมาณที่จัดเรียง (141B กับ 789B) จากนี้ต่อไป


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