เพรดิเคตของ SARGable จะถูกผลักลงใน CTE หรือตารางที่ได้รับ


15

กระสอบทราย

ขณะที่การทำงานในบล็อกด้านคุณภาพPosts®ฉันมาข้ามบางพฤติกรรมเพิ่มประสิทธิภาพผมพบว่ามันโกรธที่น่าสนใจ ฉันไม่มีคำอธิบายในทันทีอย่างน้อยก็ไม่มีใครมีความสุขดังนั้นฉันวางไว้ที่นี่ในกรณีที่มีคนฉลาดปรากฏขึ้น

ถ้าคุณต้องการที่จะทำตามที่คุณสามารถคว้า 2013 รุ่นของการถ่ายโอนข้อมูลกองมากเกินที่นี่ ฉันใช้ตารางความคิดเห็นโดยมีดัชนีเพิ่มเติมหนึ่งรายการ

CREATE INDEX [ix_ennui] ON [dbo].[Comments] ( [UserId], [Score] DESC );

คำค้นหาหนึ่ง

เมื่อผมสอบถามตารางเช่นดังนั้นฉันได้รับแผนแบบสอบถามแปลก

WITH x
    AS
     (
         SELECT   TOP 101
                  c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
         ORDER BY c.Score DESC
     )
SELECT *
FROM   x
WHERE  x.Score >= 500;

ถั่ว

เพรดิเคต SARGable บนคะแนนไม่ได้ถูกผลักเข้าไปใน CTE มันอยู่ในตัวดำเนินการตัวกรองในภายหลังในแผน

ถั่ว

ซึ่งฉันพบว่าคี่เนื่องจากORDER BYอยู่ในคอลัมน์เดียวกับตัวกรอง

แบบสอบถามสอง

ถ้าฉันเปลี่ยนแบบสอบถามมันจะถูกผลัก

WITH x
    AS
     (
         SELECT   c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
     )
SELECT TOP 101 *
FROM   x
WHERE  x.Score >= 500
ORDER BY x.Score DESC;

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

ถั่ว

ถั่ว

ข้อความค้นหาสาม

นี่คือเทียบเท่ากับการเขียนแบบสอบถามเช่น:

SELECT   TOP 101
         c.UserId, c.Text, c.Score
FROM     dbo.Comments AS c
WHERE c.Score >= 500
ORDER BY c.Score DESC;

ข้อความค้นหาสี่

การใช้ตารางที่ได้รับจะได้รับแผนการสืบค้นที่ "ไม่ดี" เหมือนกับแบบสอบถาม CTE เริ่มต้น

SELECT *
FROM   (   SELECT   TOP 101
                    c.UserId, c.Text, c.Score
           FROM     dbo.Comments AS c
           ORDER BY c.Score DESC ) AS x
WHERE x.Score >= 500;

สิ่งต่าง ๆ แม้จะแปลกเมื่อ ...

<=ฉันจะเปลี่ยนแบบสอบถามเพื่อสั่งซื้อจากน้อยไปมากข้อมูลและตัวกรองเพื่อ

เพื่อไม่ให้คำถามนี้ยาวเกินไปฉันจะรวบรวมทุกอย่างเข้าด้วยกัน

แบบสอบถาม

--Derived table
SELECT *
FROM   (   SELECT   TOP 101
                    c.UserId, c.Text, c.Score
           FROM     dbo.Comments AS c
           ORDER BY c.Score ASC ) AS x
WHERE x.Score <= 500;


--TOP inside CTE
WITH x
    AS
     (
         SELECT   TOP 101
                  c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
         ORDER BY c.Score ASC
     )
SELECT *
FROM   x
WHERE  x.Score <= 500;


--Written normally
SELECT   TOP 101
         c.UserId, c.Text, c.Score
FROM     dbo.Comments AS c
WHERE c.Score <= 500
ORDER BY c.Score ASC;

--TOP outside CTE
WITH x
    AS
     (
         SELECT   c.UserId, c.Text, c.Score
         FROM     dbo.Comments AS c
     )
SELECT TOP 101 *
FROM   x
WHERE  x.Score <= 500
ORDER BY x.Score ASC;

แผน

การเชื่อมโยงแผน

ถั่ว

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

คำถามปรากฏขึ้น!

มีเหตุผลหรือไม่ที่คำกริยา SARGable สามารถผลักได้ในบางสถานการณ์และไม่ใช่ในกรณีอื่น ๆ ? ความแตกต่างภายในเคียวรีที่เรียงลำดับจากมากไปน้อยเป็นสิ่งที่น่าสนใจ แต่ความแตกต่างระหว่างสิ่งเหล่านั้นกับสิ่งที่เรียงลำดับจากน้อยไปมาก

สำหรับผู้ที่สนใจนี่คือแผนการที่มีเพียงดัชนีในScore:

คำตอบ:


11

มีปัญหาเล็กน้อยในการเล่นที่นี่

ผลักภาคแสดงอดีต TOP

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

การหลีกเลี่ยงคือการเขียนใหม่ด้วยตนเอง ปัญหาพื้นฐานจะคล้ายกับกรณีของการผลักดันภาคที่ผ่านมาการทำงานของหน้าต่างSelOnSeqPrjยกเว้นไม่มีกฎเฉพาะที่สอดคล้องกันเช่น

ความคิดเห็นส่วนตัวของฉันคือกฎการสำรวจSelOnTopยังคงไม่ได้รับการดำเนินการเพราะผู้คนได้เขียนแบบสอบถามที่มีเจตนาTOPเพื่อพยายามจัดทำ 'รั้วการเพิ่มประสิทธิภาพ'

* โดยทั่วไปหมายถึงภาคแสดงควรปรากฏในORDER BYข้อที่เกี่ยวข้องกับTOPและทิศทางของความไม่เท่าเทียมใด ๆ ควรเห็นด้วยกับทิศทางของการเรียงลำดับ การแปลงจะต้องคำนึงถึงพฤติกรรมการเรียงลำดับของ NULL ใน SQL Server ด้วย โดยรวมข้อ จำกัด อาจหมายถึงการเปลี่ยนแปลงนี้จะไม่เป็นประโยชน์โดยทั่วไปเพียงพอในทางปฏิบัติเพื่อพิสูจน์ความพยายามในการสำรวจเพิ่มเติม

ปัญหาการคิดต้นทุน

ส่วนที่เหลืออีกแผนการดำเนินการในคำถามที่สามารถอธิบายได้ว่าเป็นทางเลือกที่ค่าใช้จ่ายตามเนื่องจากการกระจายของค่าในScoreคอลัมน์ (แถวอื่น ๆ อีกมากมาย <= 500 กว่า> = 500) และผลกระทบของเป้าหมายแถวTOPนำโดย

ตัวอย่างเช่นแบบสอบถาม:

--Written normally
SELECT TOP (101)
    c.UserId, 
    c.[Text],
    c.Score
FROM dbo.Comments AS c
WHERE
    c.Score <= 500
ORDER BY
    c.Score ASC;

... สร้างแผนที่มีภาคแสดงที่ไม่ได้ชำระชัดเจนในตัวกรอง:

ตัวกรองล่าช้าเนื่องจากเป้าหมายของแถว

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

หากเราปิดใช้งานเป้าหมายแถวด้วยคำใบ้แบบสอบถาม:

--Written normally
SELECT TOP (101)
    c.UserId, 
    c.[Text],
    c.Score
FROM dbo.Comments AS c
WHERE
    c.Score <= 500
ORDER BY
    c.Score ASC
OPTION (USE HINT ('DISABLE_OPTIMIZER_ROWGOAL'));

... แผนการดำเนินการที่ผลิตคือ:

วางแผนโดยไม่มีเป้าหมายแถว

เพรดิเคตถูกผลักเข้าสู่การสแกนในฐานะเพรดิเคตที่ไม่สามารถคัดแยกได้และค่าใช้จ่ายของแผนทั้งหมดคือ2402.32หน่วย

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

สำหรับการค้นหาด้วยScore DESCและScore >= 500กริยา:

--Written normally
SELECT TOP (101)
    c.UserId, 
    c.[Text],
    c.Score
FROM dbo.Comments AS c
WHERE
    c.Score >= 500
ORDER BY
    c.Score DESC;

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

เพรดิเคตเลือก

อีกครั้งเครื่องมือเพิ่มประสิทธิภาพพิจารณาหลายทางเลือกและเลือกสิ่งนี้ว่าเป็นตัวเลือกที่ถูกที่สุดตามปกติ

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