ทำไมการเข้าร่วมการกำจัดไม่ทำงานกับ sys.query_store_plan


10

ต่อไปนี้เป็นการทำให้เข้าใจง่ายของปัญหาประสิทธิภาพที่พบกับ Query Store:

CREATE TABLE #tears
(
    plan_id bigint NOT NULL
);

INSERT #tears (plan_id) 
VALUES (1);

SELECT
    T.plan_id
FROM #tears AS T
LEFT JOIN sys.query_store_plan AS QSP
    ON QSP.plan_id = T.plan_id;

plan_idคอลัมน์เป็นเอกสารที่เป็นคีย์หลักของsys.query_store_planแต่แผนปฏิบัติการไม่ได้ใช้เข้าร่วมการกำจัดเป็นที่คาดว่าจะ:

  1. ไม่มีการคาดการณ์คุณลักษณะจาก DMV
  2. คีย์หลัก DMV plan_idไม่สามารถซ้ำแถวจากตารางชั่วคราวได้
  3. A LEFT JOINถูกใช้ดังนั้นจึงไม่Tสามารถลบแถวออกได้

แผนการดำเนินการ

กราฟิกแผน

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

คำตอบ:


16

เอกสารประกอบนั้นทำให้เข้าใจผิดเล็กน้อย DMV เป็นมุมมองที่ไม่ปรากฏขึ้นและไม่มีคีย์หลักเช่นนี้ คำจำกัดความพื้นฐานมีความซับซ้อนเล็กน้อย แต่คำจำกัดความง่าย ๆ ของsys.query_store_planคือ:

CREATE VIEW sys.query_store_plan AS
SELECT
    PPM.plan_id
    -- various other attributes
FROM sys.plan_persist_plan_merged AS PPM
LEFT JOIN sys.syspalvalues AS P
    ON P.class = 'PFT' 
    AND P.[value] = plan_forcing_type;

นอกจากsys.plan_persist_plan_mergedนี้ยังเป็นมุมมองแม้ว่าจะต้องเชื่อมต่อผ่านการเชื่อมต่อผู้ดูแลระบบเฉพาะเพื่อดูคำจำกัดความของมัน เรียบง่ายอีกครั้ง:

CREATE VIEW sys.plan_persist_plan_merged AS   
SELECT     
    P.plan_id as plan_id,    
    -- various other attributes
FROM sys.plan_persist_plan P 
    -- NOTE - in order to prevent potential deadlock
    -- between QDS_STATEMENT_STABILITY LOCK and index locks   
    WITH (NOLOCK) 
LEFT JOIN sys.plan_persist_plan_in_memory PM
    ON P.plan_id = PM.plan_id;

ดัชนีบนsys.plan_persist_planคือ:

╔════════════════════════╦════════════════════════ ══════════════╦═════════════╗
║ index_name ║ index_description ║ index_keys ║
╠════════════════════════╬════════════════════════ ══════════════╬═════════════╣
║ plan_persist_plan_cidx ║ทำคลัสเตอร์แบบไม่ซ้ำใครตั้งอยู่บน primary ║ plan_id ║
║ plan_persist_plan_idx1 ║ nonclustered ตั้งอยู่ใน primary ║ query_id (-) ║
╚════════════════════════╩════════════════════════ ══════════════╩═════════════╝

ดังนั้นplan_idเป็นข้อ จำกัด sys.plan_persist_planที่จะไม่ซ้ำกันใน

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

ที่สำคัญเคียวรีที่กำลังดำเนินการจึงเท่ากับ:

DECLARE @t1 table (plan_id integer NOT NULL);
DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);

SELECT 
    T1.plan_id
FROM @t1 AS T1 
LEFT JOIN
(
    SELECT 
        T2.plan_id
    FROM @t2 AS T2
    LEFT JOIN @t3 AS T3 
        ON T3.plan_id = T2.plan_id
) AS Q1
    ON Q1.plan_id = T1.plan_id;

... ที่ไม่ได้เข้าร่วมการกำจัด:

ป้อนคำอธิบายรูปภาพที่นี่

การเข้าถึงประเด็นหลักของปัญหาปัญหาคือแบบสอบถามภายใน:

DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);

SELECT 
    T2.plan_id
FROM @t2 AS T2
LEFT JOIN @t3 AS T3 
    ON T3.plan_id = T2.plan_id;

... ชัดเจนการเข้าร่วมด้านซ้ายอาจส่งผลให้แถว@t2ถูกทำซ้ำเนื่องจาก@t3ไม่มีข้อ จำกัด ที่ไม่ซ้ำplan_idกัน ดังนั้นการเข้าร่วมไม่สามารถถูกยกเลิกได้:

ป้อนคำอธิบายรูปภาพที่นี่

เพื่อแก้ไขปัญหานี้เราสามารถบอกเครื่องมือเพิ่มประสิทธิภาพได้อย่างชัดเจนว่าเราไม่ต้องการplan_idค่าที่ซ้ำกัน:

DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);

SELECT DISTINCT
    T2.plan_id
FROM @t2 AS T2
LEFT JOIN @t3 AS T3 
    ON T3.plan_id = T2.plan_id;

การรวมภายนอกเพื่อ@t3สามารถยกเลิกได้:

ป้อนคำอธิบายรูปภาพที่นี่

นำไปใช้กับแบบสอบถามจริง:

SELECT DISTINCT
    T.plan_id
FROM #tears AS T
LEFT JOIN sys.query_store_plan AS QSP
    ON QSP.plan_id = T.plan_id;

อย่างเท่าเทียมกันเราสามารถเพิ่มแทนGROUP BY T.plan_id DISTINCTอย่างไรก็ตามเครื่องมือเพิ่มประสิทธิภาพสามารถให้เหตุผลอย่างถูกต้องเกี่ยวกับplan_idคุณลักษณะจนถึงมุมมองแบบซ้อนและกำจัดการรวมภายนอกทั้งสองตามที่ต้องการ:

ป้อนคำอธิบายรูปภาพที่นี่

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

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