ปรับปรุงความเร็วของการสร้างดัชนีใหม่บนเซิร์ฟเวอร์ SQL


9

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

ตอนนี้ฉันต้องการเปิดใช้งานดัชนีอีกครั้งและฉันสงสัยว่ามีสิ่งใดบ้างที่ฉันสามารถทำได้เพื่อปรับให้เหมาะสมนี้

มีตารางมากกว่า 100 ตารางและดัชนีเกือบ 2,000 รายการที่จะสร้างใหม่ ฐานข้อมูลมีขนาด 200GB

ส่วนสำคัญของสคริปต์ที่ฉันใช้คือ:

declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
    select  'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
    from    sys.indexes as i
    Inner Join sys.objects o
    On o.object_id = i.object_id
    Where o.is_ms_shipped = 0
    And i.index_id >= 1
    and i.type > 1
    and i.is_disabled = 1

ฉันถือว่าการตั้งค่า ONLINE = OFF สำหรับคำสั่งเปลี่ยนแปลงดัชนี แต่เมื่อดัชนีเริ่มต้นปิดการใช้งานฉันไม่แน่ใจว่าการตั้งค่านี้จะมีผลกระทบใด ๆ ฉันยังพิจารณาการตั้งค่า SORT_IN_TEMPDB = ON แต่เนื่องจากไฟล์ tempdb อยู่ในไดรฟ์เดียวกันกับไฟล์. mdf ของฐานข้อมูลที่ฉันคิดว่าไม่มีประโยชน์ในการทำเช่นนั้น

ขณะที่เรียกใช้สคริปต์การสร้างใหม่ฉันสังเกตว่าฉันมี CXPACKET หลายประเภทรออยู่ ฉันไม่เข้าใจจริงๆว่าทำไมถึงเป็นเช่นนั้นหรือถ้าเป็นปัญหาที่ฉันควรมองหาที่อยู่

ประเด็นสุดท้ายที่อาจเกี่ยวข้อง: เซิร์ฟเวอร์ทั้งหมดของฉันไม่ได้ใช้งานในปัจจุบันนอกเหนือจากการนำเข้าข้อมูลเข้าสู่ฐานข้อมูล ไม่มีกิจกรรมของผู้ใช้อื่น ๆ ที่ต้องพิจารณาหรือกังวล ข้อกังวลเดียวของฉันคือการนำเข้าข้อมูลไปยังฐานข้อมูลในเวลาที่สั้นที่สุด


3
เมื่อคุณพูดถึงข้อกังวลเพียงอย่างเดียวของคุณคือเวลานำเข้าคุณหมายถึงเวลาตั้งแต่เริ่มการนำเข้าจนถึงสิ้นสุดการเปิดใช้งานดัชนีอีกครั้งหรือไม่ ถ้าเป็นเช่นนั้นคุณควรปล่อยให้ดัชนีเปิดใช้งานในระหว่างการนำเข้า ดัชนี 2,000 รายการสำหรับข้อมูล 200GB ดูเหมือนว่าจะเป็นดัชนีจำนวนมาก บางทีคุณควรดูที่ DMV การใช้ดัชนีเพื่อดูว่ามีสิ่งที่สามารถลบออกได้หรือไม่
Max Vernon

1
เพื่อชี้แจงคุณต้องทำการนำเข้า 200GB เดียวกันซ้ำ ๆ และไม่ใช่แค่ครั้งเดียวใช่ไหม
Jon Seigel

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

3
ตกลง. เกี่ยวกับCXPACKETwaits: index จะสร้างดัชนีการสแกนเองใหม่ (แม้แต่ดัชนีที่ถูกสร้างใหม่ ) และการสแกนเหล่านั้นสามารถใช้การขนานได้ คุณไม่ควรกังวลเกี่ยวกับการรอคอย - การขนานกันอาจช่วยได้
Jon Seigel

คำตอบ:


10

การบรรลุประสิทธิภาพการนำเข้าที่ดีที่สุดในสถานการณ์นี้ต้องมีสามสิ่ง:

  1. เม็ดมีดฐานที่บันทึกไว้น้อยที่สุด
  2. การสร้างดัชนีที่ไม่ได้คลัสเตอร์แบบบันทึกไว้น้อยที่สุด
  3. หลีกเลี่ยงการอ่านทางกายภาพ

การบันทึกขั้นต่ำ

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

  1. ใช้แบบจำลองการกู้คืนฐานข้อมูลSIMPLEหรือBULK_LOGGED
  2. การระบุล็อคตารางและอินพุตที่จัดลำดับแล้ว (เช่นTABLOCKและORDERคำแนะนำ)

หมายเหตุด้านข้าง:

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

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

การสร้างดัชนีที่ไม่เป็นคลัสเตอร์แยกกัน

ข้อดีของการทำเช่นนี้คือ:

  1. เม็ดมีดดัชนีแบบกลุ่มสามารถบันทึกขั้นต่ำได้โดยไม่ต้องเปิดใช้งาน TF 610
  2. CREATE INDEX ถูกบันทึกไว้เล็กน้อยหากแบบจำลองการกู้คืนไม่ใช่ FULL

หลีกเลี่ยงการอ่านทางกายภาพ

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

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

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

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

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

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

สรุป

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

คุณสามารถลองเปิดใช้งาน TF 610 ก่อนที่จะโหลดข้อมูลลงในตารางที่มีดัชนีที่ไม่ได้จัดกลุ่มไว้แล้ว วิธีนี้ไม่เร็วเท่าวิธีก่อนหน้านี้ แต่อาจเร็วพอ

ดูต่อไปนี้สำหรับข้อมูลเพิ่มเติม:

คู่มือประสิทธิภาพการโหลดข้อมูล

การดำเนินการที่สามารถบันทึกอย่างน้อยที่สุด

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