เปลี่ยนแบบสอบถามเพื่อปรับปรุงการประมาณการของผู้ให้บริการ


14

ฉันมีข้อความค้นหาที่ทำงานในเวลาที่ยอมรับได้ แต่ฉันต้องการบีบประสิทธิภาพให้ได้มากที่สุด

การดำเนินการที่ฉันพยายามปรับปรุงคือ "ดัชนีค้นหา" ที่ด้านขวาของแผนจากโหนด 17

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

ฉันได้เพิ่มดัชนีที่เหมาะสม แต่ค่าประมาณที่ฉันได้รับสำหรับการดำเนินการนั้นเป็นครึ่งหนึ่งของที่ควรจะเป็น

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

ใครบ้างมีคำแนะนำเกี่ยวกับสิ่งอื่นที่ฉันสามารถลองได้บ้าง

แผนเต็มรูปแบบและรายละเอียดที่สามารถพบได้ที่นี่

แผนไม่ระบุชื่อสามารถพบได้ที่นี่

ปรับปรุง:

ฉันรู้สึกว่าคำถามเริ่มต้นสร้างความสับสนอย่างมากดังนั้นฉันจะเพิ่มรหัสดั้งเดิมพร้อมคำอธิบายบางอย่าง

create procedure [dbo].[someProcedure] @asType int, @customAttrValIds idlist readonly
as
begin
    set nocount on;

    declare @dist_ca_id int;

    select *
    into #temp
    from @customAttrValIds
        where id is not null;

    select @dist_ca_id = count(distinct CustomAttrID) 
    from CustomAttributeValues c
        inner join #temp a on c.Id = a.id;

    select a.Id
        , a.AssortmentId 
    from Assortments a
        inner join AssortmentCustomAttributeValues acav
            on a.Id = acav.Assortment_Id
        inner join CustomAttributeValues cav 
            on cav.Id = acav.CustomAttributeValue_Id
    where a.AssortmentType = @asType
        and acav.CustomAttributeValue_Id in (select id from #temp)
    group by a.AssortmentId
        , a.Id
    having count(distinct cav.CustomAttrID) = @dist_ca_id
    option(recompile);

end

คำตอบ:

  1. ทำไมการตั้งชื่อเริ่มต้นแปลก ๆ ในลิงก์ pasteThePlan

    คำตอบ : เพราะฉันใช้ anonymize plan จาก SQL Sentry Plan Explorer

  2. ทำไมOPTION RECOMPILE?

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

  3. WITH SCHEMABINDING?

    คำตอบ : ฉันต้องการหลีกเลี่ยงสิ่งนั้นจริงๆและจะใช้เฉพาะเมื่อฉันมีมุมมองที่จัดทำดัชนีไว้ อย่างไรก็ตามนี่คือฟังก์ชั่นระบบ ( COUNT()) ดังนั้นจึงไม่มีประโยชน์สำหรับSCHEMABINDINGที่นี่

คำตอบสำหรับคำถามที่เป็นไปได้มากขึ้น:

  1. ทำไมผมใช้INSERT INTO #temp FROM @customAttrributeValues?

    คำตอบ : เพราะฉันสังเกตเห็นและตอนนี้รู้ว่าเมื่อใช้ตัวแปรที่เสียบเข้ากับแบบสอบถามการประมาณการใด ๆ ที่เกิดจากการทำงานกับตัวแปรจะเป็น 1 เสมอและฉันทดสอบการใส่ข้อมูลลงในตารางชั่วคราวและค่าประมาณเท่ากับแถวที่เกิดขึ้นจริง .

  2. ผมไม่ใช้ทำไมand acav.CustomAttributeValue_Id in (select id from #temp)?

    คำตอบ : ฉันสามารถแทนที่ด้วย JOIN ใน #temp แต่นักพัฒนาสับสนมากและเสนอINตัวเลือก ฉันไม่คิดว่าจะมีความแตกต่างแม้โดยการแทนที่และไม่ว่าจะด้วยวิธีใดก็ไม่มีปัญหา


ฉันเดาว่าการ#tempสร้างและการใช้งานจะเป็นปัญหาสำหรับประสิทธิภาพไม่ใช่ผลกำไร คุณกำลังบันทึกลงในตารางที่ไม่ได้จัดทำดัชนีไว้เพื่อใช้ครั้งเดียวเท่านั้น ลองลบออกอย่างสมบูรณ์ (และอาจเปลี่ยนin (select id from #temp)เป็นexistsแบบสอบถามย่อย
ypercubeᵀᴹ

@ ypercubeᵀᴹจริงเพียงไม่กี่หน้าอ่านด้วยการใช้ตัวแปรแทนตาราง temp
Radu Gheorghiu

โดยวิธีการตัวแปรตารางจะให้การประมาณจำนวนแถวที่ถูกต้องเมื่อใช้กับตัวเลือก (Recompile) - แต่ก็ยังไม่มีสถิติแบบละเอียดความเป็นเชิงการนับ ฯลฯ
TH

@TH ฉันได้ดูแผนการดำเนินการตามจริงโดยประมาณเมื่อใช้select id from @customAttrValIdsแทนselect id from #tempและจำนวนแถวโดยประมาณ1สำหรับตัวแปรและ3สำหรับ #temp (ซึ่งตรงกับจำนวนแถวจริง) นั่นเป็นเหตุผลที่ฉันแทนที่ด้วย@ #และฉันDOจำพูดคุย (จากเบรนต์ O หรืออาโรเบอร์ทรานด์) ที่พวกเขากล่าวว่าเมื่อใช้ตัวแปร tbl ประมาณการสำหรับการที่จะเป็น 1 และการปรับปรุงที่จะได้รับการประมาณการที่ดีกว่าพวกเขาจะใช้ตารางชั่วคราว
Radu Gheorghiu

@RaduGheorghiu ใช่ แต่ในโลกพวกนั้นตัวเลือก (คอมไพล์ซ้ำ) ไม่ค่อยเป็นตัวเลือกและพวกเขาก็ชอบตารางอุณหภูมิด้วยเหตุผลที่ถูกต้องอื่น ๆ บางทีการประมาณการอาจแสดงอย่างไม่ถูกต้องว่าเป็น 1 เสมอเนื่องจากจะเปลี่ยนแผนตามที่เห็นที่นี่: theboreddba.com/Categories/FunWithFlags/ ......
TH

คำตอบ:


12

แผนดังกล่าวถูกคอมไพล์บนอินสแตนซ์ RTM ของ SQL Server 2008 R2 (รุ่น 10.50.1600) คุณควรติดตั้งService Pack 3 (บิวด์ 10.50.6000) ตามด้วยแพทช์ล่าสุดเพื่อนำไปสู่การสร้างล่าสุด (ปัจจุบัน) 10.50.6542 สิ่งนี้มีความสำคัญด้วยเหตุผลหลายประการรวมถึงความปลอดภัยการแก้ไขข้อบกพร่องและคุณสมบัติใหม่

การเพิ่มประสิทธิภาพการฝังพารามิเตอร์

เกี่ยวข้องกับคำถามปัจจุบัน SQL Server 2008 R2 RTM ไม่สนับสนุนพารามิเตอร์ฝัง Optimization (PEO) OPTION (RECOMPILE)สำหรับ ตอนนี้คุณกำลังจ่ายค่าใช้จ่ายในการคอมไพล์ซ้ำโดยไม่คำนึงถึงประโยชน์หลักอย่างใดอย่างหนึ่ง

เมื่อ PEO พร้อมใช้งาน SQL Server สามารถใช้ค่าตามตัวอักษรที่เก็บไว้ในตัวแปรและพารามิเตอร์ภายในเครื่องโดยตรงในแผนคิวรี สิ่งนี้สามารถนำไปสู่ความเรียบง่ายอย่างมากและเพิ่มประสิทธิภาพ มีข้อมูลเพิ่มเติมเกี่ยวกับว่าในบทความของฉัน, พารามิเตอร์ดมฝังและตัวเลือก RECOMPILE

Hash, Sort และ Exchange Spills

สิ่งเหล่านี้จะแสดงเฉพาะในแผนการดำเนินการเมื่อมีการรวบรวมแบบสอบถามใน SQL Server 2012 หรือใหม่กว่า ในรุ่นก่อนหน้านี้เราต้องตรวจสอบการรั่วไหลในขณะที่แบบสอบถามกำลังดำเนินการโดยใช้ Profiler หรือ Extended Events การรั่วไหลส่งผลให้ I / O ทางกายภาพไปยัง (และจาก) หน่วยเก็บข้อมูลสำรองถาวรtempdbซึ่งสามารถมีผลการทำงานที่สำคัญโดยเฉพาะอย่างยิ่งหากการรั่วไหลมีขนาดใหญ่หรือเส้นทาง I / O อยู่ภายใต้แรงกดดัน

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

นอกจากนี้ยังมีโอเปอเรเตอร์แฮช (Inner Join) ในแผน หน่วยความจำที่สงวนไว้สำหรับตารางแฮชจะขึ้นอยู่กับการประมาณการสำหรับแถวป้อนข้อมูลด้านการสอบสวน โพรบอินพุตประมาณการประมาณ 847,399 แถว แต่พบ 1,223,636 ในขณะใช้งาน ส่วนเกินนี้อาจเป็นสาเหตุของการรั่วไหลของกัญชา

การรวมซ้ำซ้อน

การจับคู่แฮช (รวม) ที่โหนด 8 ทำการดำเนินการจัดกลุ่มบน(Assortment_Id, CustomAttrID)แต่แถวอินพุตเท่ากับแถวเอาต์พุต:

โหนด 8 แฮชแมตช์ (รวม)

สิ่งนี้แสดงให้เห็นว่าการรวมกันของคอลัมน์เป็นกุญแจสำคัญ (ดังนั้นการจัดกลุ่มจึงไม่จำเป็นต้องใช้ความหมาย) ค่าใช้จ่ายในการดำเนินการรวมซ้ำซ้อนจะเพิ่มขึ้นตามความต้องการผ่าน 1.4 ล้านแถวสองครั้งในการแลกเปลี่ยนการแบ่งพาร์ติชันแบบแฮช

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

การกระจายเธรดที่ไม่มีประสิทธิภาพ

ตามที่ระบุไว้ใน คำตอบของ Joe Obbishการแลกเปลี่ยนที่โหนด 14 ใช้การแบ่งแฮชเพื่อกระจายแถวระหว่างเธรด น่าเสียดายที่จำนวนแถวและตัวจัดตารางเวลาที่มีอยู่น้อยหมายความว่าทั้งสามแถวจะสิ้นสุดในเธรดเดี่ยว เห็นได้ชัดว่าแผนขนานวิ่งตามลำดับ (มีค่าใช้จ่ายขนาน) เท่าที่การแลกเปลี่ยนที่โหนด 9

คุณสามารถระบุสิ่งนี้ (เพื่อรับการปัดเศษแบบแบ่งรอบหรือการแบ่งพาร์ทิชันแบบกระจาย) โดยกำจัด Distinct Sort ที่โหนด 13 วิธีที่ง่ายที่สุดคือการสร้างคีย์หลักแบบคลัสเตอร์บน#tempตารางและทำการดำเนินการที่แตกต่างกันเมื่อโหลดตาราง:

CREATE TABLE #Temp
(
    id integer NOT NULL PRIMARY KEY CLUSTERED
);

INSERT #Temp
(
    id
)
SELECT DISTINCT
    CAV.id
FROM @customAttrValIds AS CAV
WHERE
    CAV.id IS NOT NULL;

การแคชสถิติตารางชั่วคราว

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

เพื่อหลีกเลี่ยงปัญหานี้ให้ใช้OPTION (RECOMPILE)ร่วมกับอย่างชัดเจนUPDATE STATISTICS #TempTableหลังจากเติมข้อมูลตารางชั่วคราวและก่อนที่จะมีการอ้างอิงในแบบสอบถาม

เขียนแบบสอบถามใหม่

ส่วนนี้จะถือว่าการเปลี่ยนแปลงการสร้าง #Tempตารางได้ทำไปแล้ว

เมื่อพิจารณาถึงค่าใช้จ่ายของการรั่วไหลของแฮชที่เป็นไปได้และการรวมซ้ำซ้อน (และการแลกเปลี่ยนโดยรอบ) อาจจ่ายให้เป็นรูปธรรมที่โหนด 10

CREATE TABLE #Temp2
(
    CustomAttrID integer NOT NULL,
    Assortment_Id integer NOT NULL,
);

INSERT #Temp2
(
    Assortment_Id,
    CustomAttrID
)
SELECT
    ACAV.Assortment_Id,
    CAV.CustomAttrID
FROM #temp AS T
JOIN dbo.CustomAttributeValues AS CAV
    ON CAV.Id = T.id
JOIN dbo.AssortmentCustomAttributeValues AS ACAV
    ON T.id = ACAV.CustomAttributeValue_Id;

ALTER TABLE #Temp2
ADD CONSTRAINT PK_#Temp2_Assortment_Id_CustomAttrID
PRIMARY KEY CLUSTERED (Assortment_Id, CustomAttrID);

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

การทำให้เป็นรูปธรรมนี้มีแนวโน้มที่จะเกิดขึ้นในหน่วยความจำ (หลีกเลี่ยงtempdb I / O) หากอินสแตนซ์มีหน่วยความจำเพียงพอ นี่คือแนวโน้มที่มากยิ่งขึ้นเมื่อคุณปรับรุ่นเป็น SQL Server 2012 (SP1 CU10 / SP2 CU1 หรือหลังจากนั้น) ซึ่งได้มีการปรับปรุงพฤติกรรมเขียนกระตือรือร้น

การกระทำนี้ให้ข้อมูลความถูกต้องของเครื่องมือเพิ่มประสิทธิภาพที่แม่นยำของชุดสื่อกลางช่วยให้สามารถสร้างสถิติและช่วยให้เราสามารถประกาศ(Assortment_Id, CustomAttrID)เป็นกุญแจสำคัญได้

แผนสำหรับประชากร#Temp2ควรมีลักษณะเช่นนี้ (หมายเหตุการสแกนดัชนีแบบกลุ่มของ#Tempไม่มีการเรียงที่แตกต่างและการแลกเปลี่ยนตอนนี้ใช้การแบ่งพาร์ติชันแถวแบบโรบิน):

# ประชากร Temp2

ด้วยชุดที่พร้อมใช้งานแบบสอบถามสุดท้ายกลายเป็น:

SELECT
    A.Id,
    A.AssortmentId
FROM
(
    SELECT
        T.Assortment_Id
    FROM #Temp2 AS T
    GROUP BY
        T.Assortment_Id
    HAVING
        COUNT_BIG(DISTINCT T.CustomAttrID) = @dist_ca_id
) AS DT
JOIN dbo.Assortments AS A
    ON A.Id = DT.Assortment_Id
WHERE
    A.AssortmentType = @asType
OPTION (RECOMPILE);

เราสามารถเขียนสิ่งCOUNT_BIG(DISTINCT...ที่เรียบง่ายได้ด้วยตนเองCOUNT_BIG(*)แต่ด้วยข้อมูลสำคัญใหม่ตัวเพิ่มประสิทธิภาพนั้นทำเพื่อเรา:

แผนสุดท้าย

แผนขั้นสุดท้ายอาจใช้การเข้าร่วมวนรอบ / แฮช / การผสานขึ้นอยู่กับข้อมูลสถิติเกี่ยวกับข้อมูลที่ฉันไม่สามารถเข้าถึงได้ อีกหนึ่งบันทึกย่อขนาดเล็กอื่น ๆ : ฉันสันนิษฐานว่ามีดัชนีเช่นนี้CREATE [UNIQUE?] NONCLUSTERED INDEX IX_ ON dbo.Assortments (AssortmentType, Id, AssortmentId);อยู่

อย่างไรก็ตามสิ่งที่สำคัญเกี่ยวกับแผนสุดท้ายคือการประเมินควรดีกว่ามากและลำดับการดำเนินการจัดกลุ่มที่ซับซ้อนได้ลดลงเป็นสตรีมรวมเดียว (ซึ่งไม่ต้องการหน่วยความจำจึงไม่สามารถกระจายไปยังดิสก์)

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


9

ค่าประมาณของ cardinality นั้นดีมาก เป็นเรื่องยากที่จะได้รับจำนวนแถวโดยประมาณให้ตรงกับจำนวนแถวจริงโดยเฉพาะเมื่อคุณมีการเข้าร่วมจำนวนมาก เข้าร่วมการประเมินความผิดปกติของ cardinality นั้นเป็นเรื่องยากสำหรับเครื่องมือเพิ่มประสิทธิภาพที่จะทำให้ถูกต้อง สิ่งสำคัญที่ควรทราบคือจำนวนแถวโดยประมาณสำหรับส่วนด้านในของลูปที่ซ้อนกันนั้นเป็นการดำเนินการของลูปนั้น ดังนั้นเมื่อ SQL Server บอกว่าแถว 463869 จะถูกดึงมาพร้อมกับดัชนีหาค่าประมาณจริงในกรณีนี้คือจำนวนการประมวลผล (2) * 463869 = 927738 ซึ่งไม่ไกลจากจำนวนแถวที่แท้จริง 1391608 น่าแปลกที่ จำนวนแถวโดยประมาณใกล้จะสมบูรณ์แบบในทันทีหลังจากการวนซ้ำแบบซ้อนที่โหนด ID 10

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

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

ความไม่สมดุลของด้าย

เป็นผลให้หนึ่งเธรดทำงานกับดัชนีค้นหาทั้งหมด:

แสวงหาความไม่สมดุลของเธรด

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

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

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


-2

ฉันเชื่อว่าการประเมินที่ดีกว่าในการเข้าร่วมนั้นจะไม่เปลี่ยนแปลงแผนเว้นแต่ว่า 1.4 mill จะเป็นส่วนที่เพียงพอของตารางเพื่อให้เครื่องมือเพิ่มประสิทธิภาพเลือกดัชนี (ไม่ใช่คลัสเตอร์) สแกนด้วยการแฮชหรือการรวมเข้าด้วยกัน ฉันสงสัยว่าจะไม่ใช่กรณีที่นี่หรือไม่มีประโยชน์จริง ๆ แต่คุณสามารถทดสอบเอฟเฟกต์โดยแทนที่การเข้าร่วมภายในกับ CustomAttributeValues ​​ด้วยการเข้าร่วมแฮชภายในและการรวมเข้าด้วยกัน

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


3
มีแผนพื้นที่ขนาดใหญ่มากสำหรับแบบสอบถามนั้นมีตัวเลือกมากมายสำหรับการเข้าร่วมและการทำรัง, การขนาน, การรวมกันในท้องถิ่น / ทั่วโลก ฯลฯ ซึ่งส่วนใหญ่จะได้รับผลกระทบจากการเปลี่ยนแปลงของสถิติที่ได้รับ (การกระจายเช่นเดียวกับ cardinality ดิบ) ที่โหนดแผน 10 โปรดทราบว่าควรหลีกเลี่ยงการรวมคำใบ้ตั้งแต่เข้ามาด้วยความเงียบOPTION(FORCE ORDER)ซึ่งป้องกันไม่ให้การจัดลำดับใหม่ของเครื่องมือเพิ่มประสิทธิภาพรวมจากลำดับข้อความและการเพิ่มประสิทธิภาพอื่น ๆ อีกมากมายนอกเหนือจาก
Paul White 9

-12

คุณจะไม่ได้รับการปรับปรุงจากดัชนี [ไม่ใช่แบบคลัสเตอร์] สิ่งเดียวที่ดีกว่าการค้นหาดัชนีที่ไม่ทำคลัสเตอร์คือการค้นหาดัชนีแบบกลุ่ม

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

การเพิ่มประสิทธิภาพหลักจะเป็นการปรับ SQL Query เองหากไม่มีประสิทธิภาพใด ๆ ตัวอย่างเช่นสองสามเดือนที่ผ่านมาฉันได้รับฟังก์ชั่น SQL เพื่อให้ทำงานได้เร็วขึ้น 160 เท่าโดยเขียนSELECT UNION SELECTตารางสาระสำคัญสไตล์ใหม่เพื่อใช้ตัวPIVOTดำเนินการSQL มาตรฐาน

insert into Variable1 values (?), (?), (?)


select *
    into Object1
    from Variable2
        where Column1 is not null;



select Variable3 = Function1(distinct Column2) 
    from Object2 Object3
        inner join Object1 Object4 on Object3.Column1 = Object4.Column1;



select Object4.Column1
        , Object4.Column3 
    from Object5 Object4
        inner join Object6 Object7
            on Object4.Column1 = Object7.Column4
        inner join Object2 Object8 
            on Object8.Column1 = Object7.Column5
    where Object4.Column6 = Variable4
        and Object7.Column5 in (select Column1 from Object1)
    group by Object4.Column3
        , Object4.Column1
    having Function1(distinct Object8.Column2) = Variable3
    option(recompile);

ดังนั้นเรามาดูโดยทั่วไปจะมีประสิทธิภาพน้อยกว่ามาตรฐานSELECT * INTO INSERT Object1 (column list) SELECT column listดังนั้นฉันจะเขียนมันใหม่อีกครั้ง ถัดไปหาก Function1 ถูกกำหนดโดยไม่มี a WITH SCHEMABINDINGให้เพิ่ม aWITH SCHEMABINDINGคำสั่งควรอนุญาตให้ทำงานได้เร็วขึ้น

คุณได้เลือกนามแฝงจำนวนมากที่ไม่สมเหตุสมผลเช่น aliasing Object2 เป็น Object3 คุณควรเลือกชื่อแทนที่ดีกว่าซึ่งไม่ทำให้งงงวยรหัส คุณมี "Object7.Column5 in (เลือก Column1 จาก Object1)"

INEXISTS (SELECT 1 FROM Object1 o1 WHERE o1.Column1 = Object7.Column5)คำสั่งในลักษณะนี้มีประสิทธิภาพมากขึ้นเป็นลายลักษณ์อักษรเช่นเคย บางทีฉันควรจะเขียนอย่างอื่น EXISTSอย่างน้อยก็จะดีเท่าINมักจะมีอย่างน้อยดีเท่ามันไม่ได้ดีกว่าเสมอไป แต่มักจะเป็น

นอกจากนี้ฉันสงสัยว่าoption(recompile)กำลังปรับปรุงประสิทธิภาพการค้นหาที่นี่ ฉันจะทดสอบลบมัน


6
ถ้าการค้นหาแบบ nonclustered index ครอบคลุมการสืบค้นมันจะเป็นการดีกว่าการค้นหาแบบ cluster เพราะตามคำนิยามดัชนีแบบคลัสเตอร์จะมีคอลัมน์ทั้งหมดอยู่ในนั้นและดัชนีแบบ nonclustered จะมีคอลัมน์น้อยลงดังนั้นจะต้องค้นหาหน้าน้อยลง (และ ระดับของขั้นตอนน้อยลงในทรี b) เพื่อดึงข้อมูล ดังนั้นจึงไม่ถูกต้องที่จะกล่าวว่าดัชนีคลัสเตอร์แสวงหาจะเสมอจะดีกว่า
ErikE
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.