รีมัสชี้ให้เห็นอย่างมีประโยชน์ว่าความยาวสูงสุดของ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ที่อาจเป็นที่สนใจ มันพูดคุยเล็กน้อยเกี่ยวกับการหก, การเอียงของเกลียวและการจัดสรรหน่วยความจำสำหรับการเรียงลำดับแบบขนาน