ทำไมคำสั่งซื้อของฉันเรียงลำดับสองตารางก่อนยกเว้น (ช้า) และไม่ใช่หลัง (เร็ว)


12

ปริศนาตัวเพิ่มประสิทธิภาพการสืบค้น SQL Server 2008 R2

เรามีสองตารางทั้งสองมี 9 ล้านแถว 70,000 แถวนั้นแตกต่างกันแถวอื่นจะเหมือนกัน

อย่างรวดเร็ว 13 วินาที

select * from bigtable1
except select * from similar_bigtable2

นี่จะเรียงลำดับเอาต์พุตและยังรวดเร็ว 13 วินาทีเช่นกัน

select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column

ในขณะนี้ช้ามาก:

;with q as (
    select * from bigtable1
    except select * from similar_bigtable2
)
select * from q order by sort_column

และแม้แต่ "เคล็ดลับ" ที่บางครั้งฉันใช้เพื่อบอกใบ้ SQL Server ว่ามันจำเป็นต้องคำนวณส่วนหนึ่งของแบบสอบถามก่อนที่มันจะย้ายไปไม่ทำงานและส่งผลให้แบบสอบถามช้าเช่นกัน:

;with q as (
    select top 100 percent * from bigtable1
    except select * from similar_bigtable2
)
select * from q order by sort_column

ดูที่แบบสอบถามแผนเหตุผลไม่ยากที่จะหา:

แผนแบบสอบถาม แผนการค้นหาพร้อม ORDER BY

SQL Server วางแถวไว้สองแถวจำนวน 9 ล้านแถวก่อนแฮชแมตช์ในขณะที่ฉันต้องการเพิ่มแถว 70.000 แถวเดียวหลังจากแถวแฮชแมตช์

ดังนั้นคำถาม: ฉันจะแนะนำให้เครื่องมือเพิ่มประสิทธิภาพการสืบค้นทำเช่นนั้นได้อย่างไร


3
มันไม่เรียงลำดับก่อนที่แฮชแมตช์จะเรียงลำดับแล้วทำการผสานเข้าร่วม (ไม่ใช่การแฮชเข้าร่วม) อาจมีคำใบ้ที่จะบังคับให้เข้าร่วมแฮช (หรือป้องกันไม่ให้รวมเข้าร่วม)
Thilo

3
ดูเหมือนว่าเครื่องมือเพิ่มประสิทธิภาพการสืบค้น SQL Server ระบุว่าการเรียงลำดับข้อมูลเป็นประโยชน์ดังนั้นจึงสามารถใช้Merge Join ที่เร็วกว่า(ซึ่งใช้งานได้กับข้อมูลที่เรียงลำดับเท่านั้น) แทนที่จะใช้ Hash Match Join หรือ Nested Loop Join ที่ช้ากว่ามาก ...
marc_s

9
คุณเคยลองทางเลือกอื่นEXCEPT(เช่นOUTER JOIN) ไหม? ฉันรู้ว่าไวยากรณ์นั้นสะดวกน้อยกว่า แต่คุณอาจเล่นกับ index / join hint ได้ดีกว่านั้น (หรือคุณอาจไม่จำเป็นต้อง) ทางเลือกที่คุณใช้อยู่ตอนนี้ (สิ่งต่างๆลงในตาราง #temp ก่อน) เป็นวิธีแก้ปัญหาสุดท้าย แต่ในบางกรณีเป็นวิธีเดียวที่จะบังคับให้เครื่องมือเพิ่มประสิทธิภาพแยกสองส่วนของแบบสอบถามอย่างสมบูรณ์แบบที่คุณต้องการ
Aaron Bertrand

คำตอบ:


1

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

CTE เป็นเครื่องมือที่ยอดเยี่ยม แต่ดูเหมือนว่าจะไม่มีประสิทธิภาพในสองกรณีคือ Complex Predicates หรือ Parent / Child Key ที่ไม่ซ้ำกัน ในกรณีของคุณไม่มีคีย์ที่ไม่ซ้ำกันและเซิร์ฟเวอร์ SQL ต้องเรียงลำดับชุดข้อมูลก่อนเพื่อให้สามารถตอบสนองความต้องการของคุณได้ ดูที่ลิงค์ด้านล่างซึ่งจะบอกคุณเพิ่มเติมเกี่ยวกับปัญหานี้: http://blogs.msdn.com/b/sqlcat/archive/2011/04/28/optimize-recursive-cte-query.aspx

ดังนั้นดูเหมือนว่าคุณจะต้องยอมรับความเชื่องช้าหรือเขียนลอจิกด้วย WHILE loop ซึ่งจะมีประสิทธิภาพมากขึ้น



0

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

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