ฉันจะขอรับแผนการดำเนินการแบบสอบถามใน SQL Server ได้อย่างไร


338

ใน Microsoft SQL Server ฉันจะได้รับแผนการดำเนินการแบบสอบถามสำหรับขั้นตอนแบบสอบถาม / เก็บไว้ได้อย่างไร


2
ฉันจะปิดแท็บแผนการดำเนินการในสตูดิโอจัดการเซิร์ฟเวอร์ SQL ได้อย่างไร
Paul McCarthy

2
@Paul คุณสามารถกด Ctrl + R เพื่อดูได้ จะปิดส่วนผลลัพธ์ทั้งหมด - รวมถึงข้อความและแผนการดำเนินการ
Nisarg

คำตอบ:


501

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

วิธีที่ 1 - ใช้ Studio จัดการเซิร์ฟเวอร์ SQL

SQL Server มาพร้อมกับคุณสมบัติที่เรียบร้อยสองสามอย่างที่ทำให้ง่ายต่อการจับแผนการดำเนินการเพียงตรวจสอบให้แน่ใจว่ารายการเมนู "รวมการดำเนินการตามแผนจริง" (อยู่ใต้เมนู "แบบสอบถาม") จะถูกทำเครื่องหมายและเรียกใช้คิวรีตามปกติ .

รวมรายการเมนูแผนดำเนินการ

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

exec p_Example 42

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

สกรีนช็อตของแผนดำเนินการ

จากที่นี่คุณสามารถตรวจสอบแผนการดำเนินการใน SQL Server Management Studio หรือคลิกขวาที่แผนแล้วเลือก "บันทึกแผนปฏิบัติการเป็น ... " เพื่อบันทึกแผนเป็นไฟล์ในรูปแบบ XML

วิธีที่ 2 - การใช้ตัวเลือก SHOWPLAN

วิธีนี้คล้ายกับวิธีที่ 1 (อันที่จริงนี่คือสิ่งที่ SQL Server Management Studio ทำภายใน) แต่ฉันได้รวมไว้เพื่อความสมบูรณ์หรือถ้าคุณไม่มี SQL Server Management Studio

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

SET SHOWPLAN_TEXT ON
SET SHOWPLAN_ALL ON
SET SHOWPLAN_XML ON
SET STATISTICS PROFILE ON
SET STATISTICS XML ON -- The is the recommended option to use

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

เมื่อเสร็จแล้วคุณสามารถปิดตัวเลือกนี้ด้วยคำสั่งต่อไปนี้:

SET <<option>> OFF

การเปรียบเทียบรูปแบบแผนการดำเนินการ

คำแนะนำของฉันคือการใช้STATISTICS XMLตัวเลือก ตัวเลือกนี้เทียบเท่ากับตัวเลือก "รวมแผนการดำเนินการตามจริง" ใน SQL Server Management Studio และให้ข้อมูลมากที่สุดในรูปแบบที่สะดวกที่สุด

  • SHOWPLAN_TEXT - แสดงข้อความแผนการดำเนินการโดยประมาณตามข้อความพื้นฐานโดยไม่ต้องดำเนินการค้นหา
  • SHOWPLAN_ALL - แสดงแผนการดำเนินการตามข้อความที่มีการประมาณการต้นทุนโดยไม่ต้องดำเนินการค้นหา
  • SHOWPLAN_XML- แสดงแผนการดำเนินการโดยยึดตาม XML พร้อมการประมาณการต้นทุนโดยไม่ต้องดำเนินการค้นหา สิ่งนี้เทียบเท่ากับตัวเลือก "แสดงแผนการดำเนินการโดยประมาณ ... " ใน SQL Server Management Studio
  • STATISTICS PROFILE - ดำเนินการค้นหาและแสดงแผนปฏิบัติการจริงตามข้อความ
  • STATISTICS XML- เรียกใช้คิวรีและแสดงแผนการดำเนินการตามจริงของ XML สิ่งนี้เทียบเท่ากับตัวเลือก "รวมถึงแผนปฏิบัติการจริง" ใน SQL Server Management Studio

วิธีที่ 3 - การใช้ SQL Server Profiler

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

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

  1. เปิดตัวสร้างโปรไฟล์เซิร์ฟเวอร์ SQL และสร้างการสืบค้นกลับใหม่ที่เชื่อมต่อกับฐานข้อมูลที่คุณต้องการบันทึกการติดตาม
  2. ภายใต้แท็บ "การเลือกเหตุการณ์" ตรวจสอบ "แสดงเหตุการณ์ทั้งหมด" ตรวจสอบแถว "ประสิทธิภาพ" -> "Showplan XML" และเรียกใช้การติดตาม
  3. ในขณะที่การสืบค้นกลับกำลังทำงานให้ทำสิ่งที่คุณจำเป็นต้องทำเพื่อให้แบบสอบถามที่รันช้าทำงาน
  4. รอให้แบบสอบถามดำเนินการจนเสร็จสิ้นและหยุดการติดตาม
  5. หากต้องการบันทึกการติดตามคลิกขวาที่แผน xml ใน SQL Server Profiler และเลือก "แตกข้อมูลเหตุการณ์ ... " เพื่อบันทึกแผนเป็นไฟล์ในรูปแบบ XML

แผนที่คุณได้รับนั้นเทียบเท่ากับตัวเลือก "รวมแผนการดำเนินการตามจริง" ใน SQL Server Management Studio

วิธีที่ 4 - ตรวจสอบแคชแบบสอบถาม

หากคุณไม่สามารถเรียกใช้คิวรีของคุณโดยตรงและคุณไม่สามารถดักจับร่องรอย profiler ได้คุณยังสามารถรับแผนโดยประมาณได้โดยตรวจสอบแคชคิวรีคิวรี SQL

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

SELECT UseCounts, Cacheobjtype, Objtype, TEXT, query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)

ดำเนินการค้นหานี้และคลิกที่ XML แผนเพื่อเปิดแผนในหน้าต่างใหม่ - คลิกขวาและเลือก "บันทึกแผนการดำเนินการเป็น ... " เพื่อบันทึกแผนเป็นไฟล์ในรูปแบบ XML

หมายเหตุ:

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

คุณไม่สามารถจับแผนการดำเนินการสำหรับขั้นตอนการจัดเก็บที่เข้ารหัส

แผนการดำเนินการ "ตามจริง" เทียบกับ "โดยประมาณ"

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

ฉันจะตีความแผนการดำเนินการแบบสอบถามได้อย่างไร

นี่คือพอที่คุ้มค่าสำหรับหัวข้อ (ฟรี) หนังสือในสิทธิของตนเอง

ดูสิ่งนี้ด้วย:


8
หมายเหตุสำหรับผู้อ่านในอนาคต: ใส่SET STATISTICS XML ONant จุดเริ่มต้นของแบบสอบถามและSET STATISTICS XML OFF|ONพื้นที่โดยรอบที่คุณไม่ต้องการให้แสดงในแผนผลลัพธ์: ฉันพบว่ามีประโยชน์เมื่อแบบสอบถามมีการวนซ้ำ (WHILE) ที่คุณไม่ต้องการ / ต้องการ เพื่อดูในแผนการดำเนินการ (มิฉะนั้นจะหนักเกินไปและยาวเกินกว่าที่ SQL Server จะแสดง)
Roimer

2
@ MonsterMMORPG คุณสามารถใช้วิธีที่ 4 แล้วเลือก ตัวอย่างเช่นการใช้ <a href=" github.com/StackExchange/dapper-dot-net"> Dapper.net </ … > connection.Query <string> ("SELECT query_plan FROM sys.dm_exec_cached_plans CROSS ใช้ sys.dm_exec_sql_text (plan_handle) ) ใช้ CROSS sys.dm_exec_query_plan (plan_handle) ซึ่ง TEXT ต้องการ N '% ข้อความค้นหาดั้งเดิมของคุณไปที่นี่%' "); % คือถ้าคุณใช้ชุดย่อยของแบบสอบถาม
bmarks

2
@Justin หนังสือที่คุณเชื่อมโยงกับฉบับที่ 2 สำหรับการตีความแผนการดำเนินการสืบค้นลงวันที่ตั้งแต่ 2009 คุณจะบอกว่าเป็นทรัพยากรที่ดีสำหรับวัตถุประสงค์นั้นในปี 2016 หรือไม่?
Abdul

3
@Abdul ผู้แต่งคนเดียวกันคือ Grant Fritchey มีหนังสือเล่มใหม่ที่เรียกว่า SQL Server Query Performance Tuning ซึ่งครอบคลุม SQL Server รุ่นใหม่กว่า
เธเลม

42

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

DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID

ตัวอย่างStartCaptureคำจำกัดความ

CREATE PROCEDURE StartCapture
@Spid INT,
@TraceID INT OUTPUT
AS
DECLARE @maxfilesize BIGINT = 5
DECLARE @filepath NVARCHAR(200) = N'C:\trace_' + LEFT(NEWID(),36)

EXEC sp_trace_create @TraceID OUTPUT, 0, @filepath, @maxfilesize, NULL 

exec sp_trace_setevent @TraceID, 122, 1, 1
exec sp_trace_setevent @TraceID, 122, 22, 1
exec sp_trace_setevent @TraceID, 122, 34, 1
exec sp_trace_setevent @TraceID, 122, 51, 1
exec sp_trace_setevent @TraceID, 122, 12, 1
-- filter for spid
EXEC sp_trace_setfilter @TraceID, 12, 0, 0, @Spid
-- start the trace
EXEC sp_trace_setstatus @TraceID, 1

ตัวอย่างStopCaptureคำจำกัดความ

CREATE  PROCEDURE StopCapture
@TraceID INT
AS
WITH  XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql), 
      CTE
     as (SELECT CAST(TextData AS VARCHAR(MAX)) AS TextData,
                ObjectID,
                ObjectName,
                EventSequence,
                /*costs accumulate up the tree so the MAX should be the root*/
                MAX(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
         FROM   fn_trace_getinfo(@TraceID) fn
                CROSS APPLY fn_trace_gettable(CAST(value AS NVARCHAR(200)), 1)
                CROSS APPLY (SELECT CAST(TextData AS XML) AS xPlan) x
                CROSS APPLY (SELECT T.relop.value('@EstimatedTotalSubtreeCost',
                                            'float') AS EstimatedTotalSubtreeCost
                             FROM   xPlan.nodes('//sql:RelOp') T(relop)) ca
         WHERE  property = 2
                AND TextData IS NOT NULL
                AND ObjectName not in ( 'StopCapture', 'fn_trace_getinfo' )
         GROUP  BY CAST(TextData AS VARCHAR(MAX)),
                   ObjectID,
                   ObjectName,
                   EventSequence)
SELECT ObjectName,
       SUM(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
FROM   CTE
GROUP  BY ObjectID,
          ObjectName  

-- Stop the trace
EXEC sp_trace_setstatus @TraceID, 0
-- Close and delete the trace
EXEC sp_trace_setstatus @TraceID, 2
GO

18

สมมติว่าคุณใช้ Microsoft SQL Server Management Studio

  • สำหรับแผนแบบสอบถามโดยประมาณคุณสามารถกดCtrl + Lหรือปุ่มต่อไปนี้

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

  • สำหรับแผนแบบสอบถามจริงคุณสามารถกดCtrl + Mหรือปุ่มต่อไปนี้ก่อนดำเนินการค้นหา

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

  • สำหรับLive Query Plan (เฉพาะใน SSMS 2016) ให้ใช้ปุ่มต่อไปนี้ก่อนดำเนินการค้นหา

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


15

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

คุณสามารถติดตั้งและรวม ApexSQL Plan ลงใน SQL Server Management Studio เพื่อให้สามารถดูแผนการดำเนินการจาก SSMS ได้โดยตรง

การดูแผนปฏิบัติการโดยประมาณในแผน ApexSQL

  1. คลิกปุ่มสร้างแบบสอบถามใน SSMS และวางข้อความค้นหาในหน้าต่างข้อความค้นหา คลิกขวาและเลือกตัวเลือก“ แสดงแผนดำเนินการโดยประมาณ” จากเมนูบริบท

ปุ่มแบบสอบถามใหม่ใน SSMS

  1. แผนภาพแผนการดำเนินการจะแสดงแท็บแผนการดำเนินการในส่วนผลลัพธ์ ถัดไปคลิกขวาที่แผนการดำเนินการและในเมนูบริบทให้เลือกตัวเลือก“ เปิดในแผน ApexSQL”

แผนปฏิบัติการ

  1. แผนการดำเนินการโดยประมาณจะเปิดในแผน ApexSQL และสามารถวิเคราะห์เพื่อเพิ่มประสิทธิภาพการสืบค้น

แผนการดำเนินการโดยประมาณ

การดูแผนปฏิบัติการจริงใน ApexSQL Plan

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

คลิกปุ่ม“ จริง” จากแถบริบบิ้นหลัก

เมื่อคลิกปุ่ม "จริง" แผนดำเนินการจริงจะแสดงพร้อมภาพตัวอย่างโดยละเอียดของพารามิเตอร์ต้นทุนพร้อมกับข้อมูลแผนการดำเนินการอื่น ๆ

แผนปฏิบัติการจริง

ข้อมูลเพิ่มเติมเกี่ยวกับการดูแผนการดำเนินการสามารถพบได้โดยไปที่ลิงค์นี้


14

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

นี่คือภาพตัวอย่างหน้าจอที่คุณจะได้ทราบว่าเครื่องมือนี้มีให้ใช้งานอะไร:

ภาพหน้าจอหน้าต่าง SQL Sentry Plan Explorer ถูกยิง

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

นอกจากนี้ฉันไม่ได้สังเกตเห็นข้อ จำกัด ของรุ่นฟรีที่ป้องกันไม่ให้ใช้งานเป็นประจำทุกวันหรือบังคับให้คุณซื้อรุ่น Pro ในที่สุด ดังนั้นหากคุณต้องการติดกับรุ่นฟรีไม่มีอะไรห้ามคุณจากการทำเช่นนั้น

อัพเดท: (ขอบคุณMartin Smith ) Plan Explorer ตอนนี้ฟรี! ดูhttp://www.sqlsentry.com/products/plan-explorer/sql-server-query-viewสำหรับรายละเอียด


1
ใครกำลังพูดถึงเครื่องมือของบุคคลที่สาม
basher

12
@ ผู้ประกาศข่าว: OP ไม่ได้ จำกัด วิธีการด้วยเครื่องมือ MS หรืออย่างอื่น ดังนั้นอะไรทำให้คุณคิดว่าคำตอบที่เกี่ยวข้องกับเครื่องมือของบุคคลที่สามนั้นเป็นสิ่งที่ไม่เหมาะสม
Alexander Abakumov

3
แค่ล้อเล่นกับวิธีที่คุณใช้ถ้อยคำจุดเริ่มต้นของคำตอบSpeaking of third-party toolsเมื่อไม่มีใครพูดถึงเครื่องมือของบุคคลที่สาม
basher

4
@basher: โอ้จับได้ดี! ขอบคุณ! ฉันเขียนคำตอบใหม่แล้ว โปรดส่งข้อเสนอแนะและ / หรือโหวตถ้าคุณต้องการ
อเล็กซานเด Abakumov

3
BTW มีเพียงรุ่นเดียวตอนนี้sqlsentry.com/products/plan-explorer/sql-server-query-view
Martin Smith

7

คุณสามารถรับแผนแบบสอบถามได้จากเซสชันกิจกรรมเพิ่มเติมผ่านทาง query_post_execution_showplanกิจกรรม นี่คือเซสชัน XEvent ตัวอย่าง:

/*
    Generated via "Query Detail Tracking" template.
*/
CREATE EVENT SESSION [GetExecutionPlan] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan(
    ACTION(package0.event_sequence,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)),

/* Remove any of the following events (or include additional events) as desired. */
ADD EVENT sqlserver.error_reported(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.module_end(SET collect_statement=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.rpc_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sp_statement_completed(SET collect_object_name=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))) 
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

หลังจากคุณสร้างเซสชัน (ใน SSMS) ให้ไปที่ Object Explorer และเจาะลึกลงไปใน Management | เหตุการณ์เพิ่มเติม การประชุม คลิกขวาที่เซสชัน "GetExecutionPlan" และเริ่มต้น คลิกขวาอีกครั้งและเลือก "ดูข้อมูลสด"

ถัดไปเปิดหน้าต่างแบบสอบถามใหม่และเรียกใช้แบบสอบถามอย่างน้อยหนึ่งรายการ นี่คือหนึ่งใน AdventureWorks:

USE AdventureWorks;
GO

SELECT p.Name AS ProductName, 
    NonDiscountSales = (OrderQty * UnitPrice),
    Discounts = ((OrderQty * UnitPrice) * UnitPriceDiscount)
FROM Production.Product AS p 
INNER JOIN Sales.SalesOrderDetail AS sod
    ON p.ProductID = sod.ProductID 
ORDER BY ProductName DESC;
GO

หลังจากนั้นสักครู่หรือสองครั้งคุณจะเห็นผลลัพธ์บางอย่างในแท็บ "GetExecutionPlan: ข้อมูลสด" คลิกหนึ่งในเหตุการณ์ query_post_execution_showplan ในตารางจากนั้นคลิกแท็บ "แผนแบบสอบถาม" ด้านล่างตาราง ควรมีลักษณะคล้ายกับนี้:

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

แก้ไข : รหัส XEvent และภาพหน้าจอถูกสร้างขึ้นจาก SQL / SSMS 2012 w / SP2 หากคุณกำลังใช้ SQL 2008 / R2 คุณอาจจะสามารถที่จะปรับแต่งสคริปต์เพื่อให้ทำงาน แต่เวอร์ชันนั้นไม่มี GUI ดังนั้นคุณต้องแยก showplan XML ออกให้บันทึกเป็นไฟล์ * .sqlplan และเปิดใน SSMS มันยุ่งยาก XEvents ไม่มีอยู่ใน SQL 2005 หรือก่อนหน้า ดังนั้นหากคุณไม่ได้อยู่ใน SQL 2012 หรือใหม่กว่าฉันขอแนะนำอย่างยิ่งหนึ่งในคำตอบอื่น ๆ ที่โพสต์ไว้ที่นี่


5

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

  1. คอมโพเนนต์ที่มีอยู่ของ SQL Server โต้ตอบกับที่เก็บแบบสอบถามโดยใช้ตัวจัดการการจัดเก็บแบบสอบถาม
  2. ผู้จัดการร้านค้าแบบสอบถามกำหนดร้านค้าที่ควรใช้แล้วส่งผ่านการดำเนินการไปยังร้านค้านั้น (Plan หรือ Runtime Stats หรือ Query Wait Stats)
    • ร้านค้า Plan - เก็บข้อมูลแผนปฏิบัติการไว้
    • ที่เก็บสถิติรันไทม์ - เก็บข้อมูลสถิติการดำเนินการต่อ
    • Query Wait Stats Store - ข้อมูลสถิติการรอคอยที่คงอยู่
  3. Plan, Runtime Stats และ Wait store ใช้ Query Store เป็นส่วนขยายของ SQL Server

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

  1. การเปิดใช้งาน Query Store : Query Store ทำงานที่ระดับฐานข้อมูลบนเซิร์ฟเวอร์

    • Query Store ไม่ทำงานสำหรับฐานข้อมูลใหม่ตามค่าเริ่มต้น
    • คุณไม่สามารถเปิดใช้งานการจัดเก็บแบบสอบถามสำหรับต้นแบบหรือtempdbฐานข้อมูล
    • DMV ที่มีอยู่

      sys.database_query_store_options (Transact SQL)

  2. รวบรวมข้อมูลใน Query Store : เรารวบรวมข้อมูลที่มีทั้งหมดจากสามร้านค้าโดยใช้ Query Store DMV (มุมมองการจัดการข้อมูล)

    • Query Plan Store: ยืนยัน ข้อมูลแผนปฏิบัติการและรับผิดชอบในการรวบรวมข้อมูลทั้งหมดที่เกี่ยวข้องกับการรวบรวมแบบสอบถาม

      sys.query_store_query(Transact-SQL) sys.query_store_plan(Transact-SQL) sys.query_store_query_text(Transact-SQL)

    • ที่เก็บสถิติรันไทม์: เก็บ ข้อมูลสถิติการดำเนินการต่อและอาจเป็นที่เก็บที่อัปเดตบ่อยที่สุด สถิติเหล่านี้แสดงข้อมูลการดำเนินการแบบสอบถาม

      sys.query_store_runtime_stats (Transact SQL)

    • Query Wait Stats Store: การคงอยู่ และการเก็บข้อมูลสถิติการรอ

      sys.query_store_wait_stats (Transact SQL)

หมายเหตุ: Query Wait Stats Store มีเฉพาะใน SQL Server 2017+


4

เช่นเดียวกับสตูดิโอจัดการเซิร์ฟเวอร์ SQL (อธิบายแล้ว) ก็ยังเป็นไปได้ด้วย Datagrip ตามที่อธิบายไว้ที่นี่

  1. คลิกขวาที่คำสั่ง SQL และเลือกอธิบายแผน
  2. ในบานหน้าต่างผลลัพธ์ให้คลิกแผน
  3. โดยค่าเริ่มต้นคุณจะเห็นการแสดงแผนภูมิของแบบสอบถาม หากต้องการดูแผนคิวรีให้คลิกไอคอนแสดงการสร้างภาพหรือกด Ctrl + Shift + Alt + U

3

ต่อไปนี้เป็นสิ่งสำคัญที่ควรทราบนอกเหนือจากที่กล่าวไว้ทั้งหมด

แผนแบบสอบถามมักจะซับซ้อนเกินกว่าที่จะแสดงโดยชนิดคอลัมน์ XML ในตัวซึ่งมีข้อ จำกัด ขององค์ประกอบที่ซ้อนกัน127 ระดับ นั่นคือหนึ่งในเหตุผลที่sys.dm_exec_query_planอาจส่งคืนNULLหรือแม้แต่โยนข้อผิดพลาดใน MS SQL เวอร์ชันก่อนหน้าดังนั้นโดยทั่วไปจะปลอดภัยกว่าที่จะใช้sys.dm_exec_text_query_planแทน หลังยังมีคุณสมบัติโบนัสที่มีประโยชน์ในการเลือกแผนสำหรับคำสั่งเฉพาะมากกว่าชุดทั้งหมด นี่คือวิธีที่คุณใช้เพื่อดูแผนสำหรับคำสั่งที่รันอยู่ในปัจจุบัน:

SELECT p.query_plan
FROM sys.dm_exec_requests AS r
OUTER APPLY sys.dm_exec_text_query_plan(
                r.plan_handle,
                r.statement_start_offset,
                r.statement_end_offset) AS p

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

SELECT Tag = 1, Parent = NULL, [ShowPlanXML!1!!XMLTEXT] = query_plan
FROM sys.dm_exec_text_query_plan(
                -- set these variables or copy values
                -- from the results of the above query
                @plan_handle,
                @statement_start_offset,
                @statement_end_offset)
FOR XML EXPLICIT

3

คุณยังสามารถทำได้ผ่าน PowerShell โดยใช้ SET STATISTICS XML ON เพื่อรับแผนจริง ฉันเขียนมันเพื่อที่จะรวมแผนหลายคำสั่งไว้ในแผนเดียว

    ########## BEGIN : SCRIPT VARIABLES #####################
    [string]$server = '.\MySQLServer'
    [string]$database = 'MyDatabase'
    [string]$sqlCommand = 'EXEC sp_ExampleSproc'
    [string]$XMLOutputFileName = 'sp_ExampleSproc'
    [string]$XMLOutputPath = 'C:\SQLDumps\ActualPlans\'
    ########## END   : SCRIPT VARIABLES #####################

    #Set up connection
    $connectionString = "Persist Security Info=False;Integrated Security=true;Connection Timeout=0;Initial Catalog=$database;Server=$server"
    $connection = new-object system.data.SqlClient.SQLConnection($connectionString)

    #Set up commands
    $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
    $command.CommandTimeout = 0
    $commandXMLActPlanOn = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML ON",$connection)
    $commandXMLActPlanOff = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML OFF",$connection)

    $connection.Open()

    #Enable session XML plan
    $result = $commandXMLActPlanOn.ExecuteNonQuery()

    #Execute SP and return resultsets into a dataset
    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $adapter.Fill($dataSet) | Out-Null

    #Set up output file name and path
    [string]$fileNameDateStamp = get-date -f yyyyMMdd_HHmmss
    [string]$XMLOutputFilePath = "$XMLOutputPath$XMLOutputFileName`_$fileNameDateStamp.sqlplan"

    #Pull XML plans out of dataset and merge into one multi-statement plan
    [int]$cntr = 1
    ForEach($table in $dataset.Tables)
    {
            if($table.Columns[0].ColumnName -eq "Microsoft SQL Server 2005 XML Showplan")
            {

                [string]$fullXMLPlan = $Table.rows[0]."Microsoft SQL Server 2005 XML Showplan"

                if($cntr -eq 1)
                    {

                    [regex]$rx = "\<ShowPlanXML xmlns\=.{1,}\<Statements\>"
                    [string]$startXMLPlan = $rx.Match($fullXMLPlan).Value
                    [regex]$rx = "\<\/Statements\>.{1,}\<\/ShowPlanXML\>"
                    [string]$endXMLPlan = $rx.Match($fullXMLPlan).Value

                    $startXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                    }

                [regex]$rx = "\<StmtSimple.{1,}\<\/StmtSimple\>"
                [string]$bodyXMLPlan = $rx.Match($fullXMLPlan).Value

                $bodyXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                $cntr += 1
            } 
    }

    $endXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

    #Disable session XML plan
    $result = $commandXMLActPlanOff.ExecuteNonQuery()

    $connection.Close()

2

ตามที่อธิบายไว้ในบทความนี้มีแผนปฏิบัติการสองประเภทที่คุณสามารถรับได้เมื่อใช้ SQL Server

แผนการดำเนินการโดยประมาณ

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

เพื่อให้ได้รับแผนการดำเนินการโดยประมาณคุณต้องเปิดใช้งานการSHOWPLAN_ALLตั้งค่าก่อนดำเนินการค้นหา

SET SHOWPLAN_ALL ON

ตอนนี้เมื่อดำเนินการค้นหา SQL ต่อไปนี้:

SELECT p.id
FROM post p
WHERE EXISTS (
  SELECT 1
  FROM post_comment pc
  WHERE
    pc.post_id = p.id AND
    pc.review = 'Bingo'
)
ORDER BY p.title
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY

SQL Server จะสร้างแผนการดำเนินการโดยประมาณต่อไปนี้:

| NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost | EstimateExecutions |
|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|--------------------|
| 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03374284       | NULL               |
| 2      | 1      | Top                  | 10           | 0           | 3.00E-06    | 15         | 0.03374284       | 1                  |
| 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000504114 | 146        | 0.03373984       | 1                  |
| 5      | 4      | Inner Join           | 46.698       | 0           | 0.00017974  | 146        | 0.02197446       | 1                  |
| 6      | 5      | Clustered Index Scan | 43           | 0.004606482 | 0.0007543   | 31         | 0.005360782      | 1                  |
| 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0161733        | 43                 |

หลังจากเรียกใช้แบบสอบถามเราสนใจที่จะรับแผนการดำเนินการโดยประมาณคุณต้องปิดการใช้งานSHOWPLAN_ALLมิฉะนั้นเซสชันฐานข้อมูลปัจจุบันจะสร้างแผนการดำเนินการโดยประมาณเท่านั้นแทนที่จะดำเนินการแบบสอบถาม SQL ที่มีให้

SET SHOWPLAN_ALL OFF

SQL Server Studio Studio ประมาณการแผน

ในแอปพลิเคชัน SQL Server Management Studio คุณสามารถรับแผนการดำเนินการโดยประมาณสำหรับแบบสอบถาม SQL ใด ๆ ได้โดยกดปุ่มCTRL+Lทางลัด

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

แผนปฏิบัติการจริง

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

ในการรับแผนปฏิบัติการจริงบน SQL Server คุณต้องเปิดใช้งานการSTATISTICS IO, TIME, PROFILEตั้งค่าดังที่แสดงโดยคำสั่ง SQL ต่อไปนี้:

SET STATISTICS IO, TIME, PROFILE ON

ตอนนี้เมื่อเรียกใช้คิวรีก่อนหน้า SQL Server จะสร้างแผนการดำเนินการต่อไปนี้:

| Rows | Executes | NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost |
|------|----------|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|
| 10   | 1        | 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03338978       |
| 10   | 1        | 2      | 1      | Top                  | 1.00E+01     | 0           | 3.00E-06    | 15         | 0.03338978       |
| 30   | 1        | 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000478783 | 146        | 0.03338679       |
| 41   | 1        | 5      | 4      | Inner Join           | 44.362       | 0           | 0.00017138  | 146        | 0.02164674       |
| 41   | 1        | 6      | 5      | Clustered Index Scan | 41           | 0.004606482 | 0.0007521   | 31         | 0.005358581      |
| 41   | 41       | 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0158571        |

SQL Server parse and compile time:
   CPU time = 8 ms, elapsed time = 8 ms.

(10 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post'. Scan count 0, logical reads 116, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post_comment'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(6 row(s) affected)

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

หลังจากเรียกใช้แบบสอบถามเราสนใจที่จะรับแผนปฏิบัติการจริงคุณต้องปิดการใช้งานการSTATISTICS IO, TIME, PROFILE ONตั้งค่าดังนี้:

SET STATISTICS IO, TIME, PROFILE OFF

แผนจริงของ Studio จัดการเซิร์ฟเวอร์ SQL

ในแอปพลิเคชัน SQL Server Management Studio คุณสามารถรับแผนการดำเนินการโดยประมาณสำหรับแบบสอบถาม SQL ใด ๆ ได้โดยกดปุ่มCTRL+Mทางลัด

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

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการแผนการดำเนินการเมื่อใช้ SQL Server, ตรวจสอบบทความนี้


0

การอธิบายแผนการดำเนินการสามารถมีรายละเอียดมากและใช้เวลาในการอ่านค่อนข้างนาน แต่โดยสรุปหากคุณใช้ 'อธิบาย' ก่อนที่แบบสอบถามจะให้ข้อมูลมากมายรวมถึงส่วนใดที่ถูกเรียกใช้ก่อน หากคุณต้องการอ่านรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ฉันได้รวบรวมบล็อกเล็ก ๆ เกี่ยวกับสิ่งนี้ซึ่งชี้ให้คุณเห็นถึงการอ้างอิงที่ถูกต้อง https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

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