แบบสอบถาม T-SQL โดยใช้แผนแตกต่างกันอย่างสมบูรณ์ขึ้นอยู่กับจำนวนแถวที่ฉันกำลังอัปเดต


20

ฉันมีคำสั่ง SQL UPDATE พร้อมประโยค "TOP (X)" และแถวที่ฉันอัปเดตค่ามีประมาณ 4 พันล้านแถว เมื่อฉันใช้ "TOP (10)" ฉันจะได้รับแผนการดำเนินการหนึ่งแผนซึ่งจะดำเนินการเกือบจะทันที แต่เมื่อฉันใช้ "TOP (50)" หรือใหญ่กว่าแบบสอบถามจะไม่เสร็จสิ้น (อย่างน้อยไม่ใช่ในขณะที่ฉันรอ) มันใช้แผนการดำเนินการที่แตกต่างอย่างสิ้นเชิง เคียวรีขนาดเล็กใช้แผนอย่างง่ายมากที่มีคู่ของการค้นหาดัชนีและการเข้าร่วมลูปที่ซ้อนกันซึ่งแบบสอบถามเดียวกันที่แน่นอน (มีจำนวนแถวที่แตกต่างกันในส่วนคำสั่งย่อยด้านบนของคำสั่ง UPDATE) ใช้แผนที่เกี่ยวข้องกับการค้นหาดัชนีสองรายการ สปูลของตารางการขนานและความซับซ้อนอื่น ๆ

ฉันใช้ "OPTION (ใช้แผน ... )" เพื่อบังคับให้ใช้แผนการดำเนินการที่สร้างโดยเคียวรีขนาดเล็ก - เมื่อฉันทำสิ่งนี้ฉันสามารถอัปเดตได้มากถึง 100,000 แถวในไม่กี่วินาที ฉันรู้ว่าแผนการสืบค้นเป็นสิ่งที่ดี แต่ SQL Server จะเลือกแผนนั้นด้วยตัวเองเมื่อมีจำนวนแถวที่เกี่ยวข้องน้อย - จำนวนแถวที่มีขนาดใหญ่พอสมควรในการอัปเดตของฉันจะส่งผลให้แผนย่อยดีที่สุด

ฉันคิดว่าการขนานกันนั้นอาจจะเป็นความผิดดังนั้นฉันจึงตั้งMAXDOP 1คำถาม แต่ไม่มีผลใด ๆ - ขั้นตอนนั้นหายไป แต่ตัวเลือก / ประสิทธิภาพไม่ดี sp_updatestatsเช้านี้ฉันก็วิ่งไปด้วยเพื่อให้แน่ใจว่าไม่ใช่สาเหตุ

ฉันได้แนบแผนปฏิบัติการสองแผน - แผนที่สั้นกว่าก็เป็นแผนที่เร็วกว่าด้วย นอกจากนี้ต่อไปนี้เป็นคำถามที่ถาม (น่าสังเกตว่า SELECT ที่ฉันรวมไว้ดูเหมือนว่าจะรวดเร็วในกรณีของจำนวนแถวทั้งเล็กและใหญ่):

    update top (10000) FactSubscriberUsage3
               set AccountID = sma.CustomerID
    --select top 50 f.AccountID, sma.CustomerID
      from FactSubscriberUsage3 f
      join dimTime t
        on f.TimeID = t.TimeID
      join #mac sma
        on f.macid = sma.macid
       and t.TimeValue between sma.StartDate and sma.enddate 
     where f.AccountID = 0 --There's a filtered index on the table for this

นี่คือแผนด่วน : แผนปฏิบัติการด่วน

และนี่คือสิ่งที่ช้ากว่า : แผนปฏิบัติการช้า

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

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

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

นี่คือข้อมูลสรุปสำหรับ 10, 100 และ 1,000 แถว - คุณจะเห็นได้ว่าการสืบค้น 1,000 แถวนั้นเป็นไปในทิศทางเดียวกันกับที่อื่น ๆ : สรุปงบ

คุณจะเห็นว่าแบบสอบถามที่สามมีจำนวนการอ่านที่ไร้สาระดังนั้นจึงเห็นได้ชัดว่าการทำสิ่งที่แตกต่างอย่างสิ้นเชิง นี่คือแผนการดำเนินการโดยประมาณที่มีการนับแถว แผนการดำเนินการประมาณ 1,000 แถว: แผนการดำเนินการโดยประมาณ 1,000 แถว

และนี่คือผลลัพธ์ที่แท้จริงของแผนการดำเนินการ (ตามวิธีโดย "ไม่เสร็จสิ้น" ปรากฎว่าฉันหมายถึง "เสร็จสิ้นในหนึ่งชั่วโมง") แผนการดำเนินการจริง 1,000 แถว แผนการดำเนินการจริง 1,000 แถว

สิ่งแรกที่ผมสังเกตเห็นก็คือว่าแทนที่จะดึง 60K แถวจากตาราง dimTime เช่นนั้นคาดว่าก็จริงดึง1600000000 กับ B ดูที่การสืบค้นของฉันฉันไม่แน่ใจว่ามันดึงแถวจำนวนมากออกจากตาราง dimTime อย่างไร ตัวดำเนินการระหว่างที่ฉันกำลังใช้เพียงแค่ให้แน่ใจว่าฉันดึงระเบียนที่ถูกต้องจาก #mac ตามบันทึกเวลาในตารางข้อเท็จจริง อย่างไรก็ตามเมื่อฉันเพิ่มบรรทัดในส่วนคำสั่ง WHERE ที่ฉันกรอง t.TimeValue (หรือ t.TimeID) เป็นค่าเดียวฉันสามารถอัปเดตแถว 100,000 แถวได้ในไม่กี่วินาที จากสิ่งนั้นและอย่างชัดเจนในแผนการดำเนินการที่ฉันรวมไว้มันชัดเจนว่าตารางเวลาของฉันเป็นปัญหา แต่ฉันไม่แน่ใจว่าฉันจะเปลี่ยนเกณฑ์การเข้าร่วมเพื่อแก้ไขปัญหานี้และรักษาความถูกต้องได้อย่างไร . ความคิดใด ๆ

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


มันเป็นสถิติ GOTTA คุณเรียกใช้sp_updatestatisticsบนโต๊ะหรือไม่?
JNK

@JNK: ตอนแรกฉันคิดอย่างนั้น แต่ได้เรียกใช้ sp_updatestats แล้วโดยไม่มีการเปลี่ยนแปลง ฉันเพิ่งรันอีกครั้งและไม่สนใจที่จะอัปเดตสถิติของดัชนีใด ๆ ที่เกี่ยวข้องในแบบสอบถาม ขอบคุณนะ!
SqlRyan

อันที่สองคือแผนการอัพเดตแบบกว้าง (ต่อดัชนี) แทนที่จะเป็นแบบแคบ (ต่อแถว) ซึ่งอธิบายถึงความซับซ้อนที่มองเห็นได้บางส่วน แต่จริงๆแล้วความแตกต่างเพียงอย่างเดียวคือการเข้าร่วมลำดับfrom #mac sma join f on f.macid = sma.macid join dimTime t on f.TimeID = t.TimeID and t.TimeValue between sma.StartDate and sma.enddatevsfrom #mac join t on t.TimeValue between sma.StartDate and sma.enddate join f on f.TimeID = t.TimeID and f.macid = sma.macid
Martin Smith

มีบางอย่างไม่ถูกต้องที่นี่ แม้แต่แผนคิวรีที่มีราคาแพงก็ควรสร้างแถวเพิ่มขึ้น ยังTOP 50ควรดำเนินการอย่างรวดเร็ว คุณสามารถอัปโหลดแผน XML ได้หรือไม่ ฉันต้องดูจำนวนแถว คุณสามารถรันTOP 50with with maxdop 1 และเป็นตัวเลือกไม่ใช่เป็นการอัปเดตและโพสต์แผนหรือไม่ (พยายามทำให้ / ค้นหาพื้นที่เป็นสองเท่า)
usr

การเข้าร่วม @usr บนt.TimeValue between sma.StartDate and sma.enddateอาจจบลงสร้างแถวที่ไร้ประโยชน์มากขึ้นในภายหลังซึ่งถูกกรองออกจากการเข้าร่วมกับ FactSubscriber และดังนั้นอย่าจบลงด้วยผลลัพธ์สุดท้าย
Martin Smith

คำตอบ:


3

ดัชนีบน dimTime กำลังเปลี่ยนแปลง แผนที่เร็วกว่านั้นใช้ดัชนี _dta ก่อนอื่นตรวจสอบให้แน่ใจว่าไม่ได้ทำเครื่องหมายเป็นดัชนีสมมุติใน sys.indexes

คิดว่าคุณสามารถเลี่ยงการตั้งค่าพารามิเตอร์บางอย่างได้โดยใช้ตาราง #mac เพื่อกรองแทนการระบุวันที่เริ่มต้น / สิ้นสุดเช่น WHERE t.TimeValue ระหว่าง @StartDate และ @enddate กำจัดตารางอุณหภูมินั้น


ดัชนีนำหน้า dta ดูเหมือนว่าถูกสร้างขึ้นโดยทำตามคำแนะนำ DTA โดยไม่ต้องกำหนดชื่อเอง ดัชนีเชิงสมมุติฐานไม่สามารถปรากฏในแผนการดำเนินการตามจริงได้ ไม่แน่ใจว่าข้อเสนอแนะที่สองของคุณจะทำงานอย่างไร t.TimeValue between sma.StartDate and sma.enddateมีความสัมพันธ์กันดังนั้นสามารถเปลี่ยนแปลงสำหรับแต่ละแถวใน#tempตาราง OP จะแทนที่อะไรด้วย
Martin Smith

ยุติธรรมพอฉันไม่ได้ใส่ใจเพียงพอกับตารางอุณหภูมิ
william_a_dba

1
อย่างไรก็ตามดัชนีสมมุติฐานสามารถทำให้แผนการดำเนินการเกิดขึ้นจริงได้ ถ้ามันเป็นสมมติฐานมันควรจะลดลงและสร้างใหม่ blogs.technet.com/b/anurag_sharma/archive/2008/04/15/…
william_a_dba

ดัชนีเชิงสัมพัทธภาพจะถูกทิ้งไว้เมื่อ DTA ไม่เสร็จ / หยุดก่อนที่จะเสร็จสิ้น คุณต้องทำความสะอาดด้วยตนเองหากมีอาการสะอึกกับ DTA
william_a_dba

1
@william_a_dba - อ่าฉันเห็นว่าคุณหมายถึงอะไรตอนนี้ (หลังจากอ่านลิงก์ของคุณ) แบบสอบถามไม่เคยเสร็จสิ้นอาจเป็นเพราะการรวบรวมซ้ำอย่างต่อเนื่อง ! ที่น่าสนใจ
Martin Smith

1

OPTION (FORCE ORDER)โดยข้อมูลเพิ่มเติมเกี่ยวกับการนับจำนวนแถวในแผนข้อเสนอแนะเบื้องต้นของฉันคือการเตรียมการสำหรับการที่ถูกต้องเข้าร่วมการสั่งซื้อในการสอบถามและบังคับใช้ บังคับใช้ลำดับการเข้าร่วมของแผนแรก

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