เหตุใดข้อความค้นหาที่คล้ายกันเหล่านี้จึงใช้ขั้นตอนการเพิ่มประสิทธิภาพที่แตกต่างกัน (การประมวลผลธุรกรรมกับแผนด่วน)


12

รหัสตัวอย่างในรายการเชื่อมต่อนี้

แสดงข้อบกพร่องที่

SELECT COUNT(*)
FROM   dbo.my_splitter_1('2') L1
       INNER JOIN dbo.my_splitter_1('') L2
         ON L1.csv_item = L2.csv_item

ส่งคืนผลลัพธ์ที่ถูกต้อง แต่ผลลัพธ์ต่อไปนี้จะส่งกลับผลลัพธ์ที่ไม่ถูกต้อง (เมื่อปี 2014 โดยใช้เครื่องมือประมาณการ Cardinality ใหม่)

SELECT
    (SELECT COUNT(*)
    FROM dbo.my_splitter_1('2') L1
     INNER JOIN dbo.my_splitter_1('') L2
        ON L1.csv_item = L2.csv_item)

เนื่องจากมันโหลดผลลัพธ์อย่างไม่ถูกต้องสำหรับ L2 ลงในสปูลนิพจน์ย่อยทั่วไปจากนั้นรีเพลย์ผลลัพธ์ของผลลัพธ์นั้นสำหรับผลลัพธ์ L1

ฉันอยากรู้ว่าทำไมความแตกต่างของพฤติกรรมระหว่างสองข้อความค้นหา Trace ธง 8675 แสดงให้เห็นว่าคนที่ทำงานเข้ามาและเป็นคนที่ไม่เข้าsearch(0) - transaction processingsearch(1) - quick plan

ดังนั้นฉันคิดว่าความพร้อมใช้งานของกฎการแปลงเพิ่มเติมอยู่เบื้องหลังความแตกต่างในพฤติกรรม (ปิดการใช้งาน BuildGbApply หรือGenGbApplySimpleดูเหมือนจะแก้ไขได้)

แต่ทำไมทั้งสองแผนสำหรับข้อความค้นหาที่คล้ายกันเหล่านี้จึงพบกับขั้นตอนการเพิ่มประสิทธิภาพที่แตกต่างกัน จากสิ่งที่ฉันอ่านsearch (0)ต้องมีอย่างน้อยสามตารางและเงื่อนไขนั้นไม่พบในตัวอย่างแรก

คำตอบ:


7

แต่ละด่านมีเงื่อนไขการเข้า "มีการอ้างอิงตารางอย่างน้อยสาม" เป็นหนึ่งในเงื่อนไขการเข้าร่วมที่เราพูดถึงเมื่อให้ตัวอย่างง่ายๆ แต่ไม่ใช่เพียงหนึ่งเดียว

โดยทั่วไปจะอนุญาตให้เข้าร่วมและสหภาพขั้นพื้นฐานเท่านั้นเมื่อเข้าสู่การค้นหา 0; เคียวรี่ย่อยแบบ scalar, semi joins เป็นต้นป้องกันการป้อนข้อมูลเพื่อค้นหา 0 ขั้นตอนนี้มีไว้สำหรับรูปร่างแบบสอบถามชนิด OLTP ทั่วไป กฎที่จำเป็นในการสำรวจสิ่งที่พบได้น้อยกว่านั้นไม่ได้เปิดใช้งาน แบบสอบถามตัวอย่างของคุณมีแบบสอบถามย่อยสเกลาร์ดังนั้นจึงไม่สามารถเข้าได้

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

ข้อผิดพลาดกับGenGbApplySimpleน่าเกลียด รูปร่างแผนนี้ก็มักจะเป็นไปได้ แต่ถูกปฏิเสธด้วยเหตุผลค่าใช้จ่ายจนกว่าจะมีการเปลี่ยนแปลงไป 100 แถวสันนิษฐานตัวแปรตาราง cardinality มา. มันเป็นไปได้ที่จะบังคับให้รูปร่างแผนมีปัญหาเกี่ยวกับการ pre-2014 CE กับUSE PLANคำใบ้ยกตัวอย่างเช่น

คุณถูกต้องเกี่ยวกับรายการการเชื่อมต่อใหม่เป็นปัญหาเดียวกันรายงานก่อนหน้านี้

เพื่อให้ตัวอย่างเคียวรีต่อไปนี้มีคุณสมบัติเหมาะสมสำหรับการค้นหา 0:

DECLARE @T AS table (c1 integer NULL);

SELECT U.c1, rn = ROW_NUMBER() OVER (ORDER BY U.c1) 
FROM 
(
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
) AS U;

การเปลี่ยนแปลงเล็กน้อยเพื่อรวมแบบสอบถามย่อยแบบสเกลาร์หมายความว่าตรงไปที่การค้นหา 1:

DECLARE @T AS table (c1 integer NULL);

SELECT U.c1, rn = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -- Changed!
FROM 
(
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
    UNION
    SELECT c1 FROM @T AS T
) AS U;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.