SELECT TOP 1 จากตารางที่มีขนาดใหญ่มากในคอลัมน์ดัชนีนั้นช้ามาก แต่ไม่ใช่ด้วยลำดับย้อนกลับ (“ desc”)


17

เรามีฐานข้อมูลขนาดใหญ่ประมาณ 1TB ใช้ SQL Server 2014 บนเซิร์ฟเวอร์ที่ทรงพลัง ทุกอย่างทำงานได้ดีไม่กี่ปี ประมาณ 2 สัปดาห์ที่ผ่านมาเราทำการบำรุงรักษาอย่างสมบูรณ์ซึ่งรวมถึง: ติดตั้งอัปเดตซอฟต์แวร์ทั้งหมด สร้างดัชนีและไฟล์ฐานข้อมูลขนาดกะทัดรัดทั้งหมด อย่างไรก็ตามเราไม่ได้คาดหวังว่าในบางช่วงการใช้งาน CPU ของ DB จะเพิ่มขึ้นมากกว่า 100% เป็น 150% เมื่อการโหลดจริงเหมือนกัน

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

select top 1 EventID from EventLog with (nolock) order by EventID

ใช้เวลาประมาณ 1.5 วินาทีเสมอ! อย่างไรก็ตามเคียวรีที่คล้ายกันที่มี "desc" จะใช้เวลาประมาณ 0 ms:

select top 1 EventID from EventLog with (nolock) order by EventID desc

PTable มีประมาณ 500 ล้านแถว; EventIDคือคอลัมน์ดัชนีคลัสเตอร์หลัก (เรียงลำดับASC) ด้วยชนิดข้อมูลของ bigint (คอลัมน์ข้อมูลประจำตัว) มีหลายเธรดที่ใส่ข้อมูลลงในตารางที่ด้านบน (EventID ที่ใหญ่กว่า) และมี 1 เธรดการลบข้อมูลจากด้านล่าง (EventID ที่เล็กกว่า)

ใน SMSS เราตรวจสอบว่าคำค้นหาสองคำนั้นใช้แผนการดำเนินการเดียวกันเสมอ:

  • การสแกนดัชนีแบบคลัสเตอร์

  • หมายเลขแถวโดยประมาณและจริงมีทั้ง 1;

  • จำนวนการประหารชีวิตโดยประมาณและที่แท้จริงคือทั้ง 1

  • ค่าใช้จ่าย I / O โดยประมาณคือ 8500 (น่าจะสูง)

  • หากดำเนินการติดต่อกันต้นทุนการสืบค้นจะเท่ากับ 50% สำหรับทั้งคู่

ฉันอัพเดตสถิติดัชนี with fullscanปัญหายังคงมีอยู่ ฉันสร้างดัชนีอีกครั้งและดูเหมือนว่าปัญหาจะหายไปครึ่งวัน แต่กลับมาแล้ว

ฉันเปิดสถิติ IO ด้วย:

set statistics io on

จากนั้นเรียกใช้แบบสอบถามทั้งสองติดต่อกันและพบข้อมูลต่อไปนี้:

(สำหรับการสืบค้นแรกแบบสอบถามที่ช้า)

ตาราง 'PTable' จำนวนการสแกน 1, ตรรกะอ่าน 407670, การอ่านทางกายภาพ 0, การอ่านล่วงหน้าอ่าน 0, lob ตรรกะอ่าน 0, lob การอ่านทางกายภาพ 0, lob การอ่านล่วงหน้าอ่าน 0

(สำหรับข้อความค้นหาที่สองหมายถึงข้อความที่รวดเร็ว)

ตาราง 'PTable' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 4, การอ่านทางกายภาพ 0, การอ่านล่วงหน้าอ่าน 0, lob การอ่านตรรกะ 0, lob ทางกายภาพอ่าน 0, lob การอ่านล่วงหน้าอ่าน 0

สังเกตความแตกต่างอย่างมากในการอ่านเชิงตรรกะ ดัชนีถูกใช้ในทั้งสองกรณี

การแตกตัวของดัชนีสามารถอธิบายได้เล็กน้อย แต่ฉันเชื่อว่าผลกระทบมีน้อยมาก และปัญหาไม่เคยเกิดขึ้นมาก่อน หลักฐานอื่นคือถ้าฉันเรียกใช้แบบสอบถามเช่น:

select * from EventLog with (nolock) where EventID=xxxx   

แม้ว่าฉันจะตั้งค่า xxxx ให้เป็น EventID ที่เล็กที่สุดในตารางการสืบค้นนั้นรวดเร็วมาก

เราตรวจสอบแล้วและไม่มีปัญหาการล็อค / การบล็อก

หมายเหตุ: ฉันพยายามลดความซับซ้อนของปัญหาด้านบน "PTable" เป็นจริง "EventLog"; PIDคือEventIDคือ

ฉันได้รับการทดสอบผลลัพธ์เดียวกันโดยไม่มีNOLOCKคำใบ้

ใครช่วยได้บ้าง

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

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

แผนการดำเนินการแบบสอบถามแบบละเอียดเพิ่มเติมใน XML ดังต่อไปนี้:

https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob

https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ

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

ตารางที่ถูกสร้างขึ้นตามปกติกับEventIDคอลัมน์เป็นคีย์หลักซึ่งเป็นคอลัมน์ประเภทidentity bigintในเวลานี้ฉันเดาว่าปัญหาอยู่ที่การแตกแฟรกเมนต์ดัชนี ทันทีหลังจากสร้างดัชนีใหม่ปัญหาดูเหมือนจะหายไปครึ่งวัน แต่ทำไมมันกลับมาอย่างรวดเร็ว ... ?

คำตอบ:


18

การสแกนดัชนีแบบคลัสเตอร์แสดงการอ่านโลจิคัล 423,723 เพื่อกลับแถวแรกโดยใช้เวลา 1926 มิลลิวินาที:

ถั่ว

ดูเหมือนจะค่อนข้างมากในการค้นหาแถวแรกในลำดับดัชนี

เป็นไปได้ว่างานการล้างข้อมูลผีของคุณนั้นใช้เวลานานหรือหยุดทำงาน คุณควรตรวจสอบghost_record_countดัชนีคลัสเตอร์sys.dm_db_index_physical_statsและติดตามการเปลี่ยนแปลงตลอดเวลา

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

ปัจจัยที่มีผลต่อประสิทธิภาพการทำงานอีกประการหนึ่งคือการสแกนตัวเองมีหน้าที่รับผิดชอบในการลบบันทึกผีตามที่กล่าวไว้ในInside Engine Storage: Ghost Cleanup ในเชิงลึกโดย Paul Randal

คุณควรตรวจสอบว่าค่าสถานะการสืบค้นกลับ 661 (ปิดใช้งานการล้างข้อมูลโกสต์) ไม่ทำงาน

โซลูชั่น

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

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

ในกรณีเฉพาะของคุณ:

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

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