Làm cách nào để có được Kế hoạch thực hiện truy vấn trong SQL Server?


338

Trong Microsoft SQL Server, làm cách nào tôi có thể nhận được một kế hoạch thực hiện truy vấn cho một thủ tục truy vấn / được lưu trữ?


2
Làm cách nào để đóng tab Kế hoạch thực hiện trong phòng quản lý máy chủ SQL?
Paul McCarthy

2
@Paul Bạn có thể nhấn Ctrl + R cho điều đó. Nó đóng toàn bộ phần kết quả - bao gồm các thông báo và kế hoạch thực hiện.
Nisarg

Câu trả lời:


500

Có một số phương pháp để có được một kế hoạch thực hiện, phương pháp nào sẽ sử dụng sẽ phụ thuộc vào hoàn cảnh của bạn. Thông thường, bạn có thể sử dụng SQL Server Management Studio để lấy kế hoạch, tuy nhiên nếu vì lý do nào đó bạn không thể chạy truy vấn của mình trong SQL Server Management Studio thì bạn có thể thấy hữu ích khi có thể lấy kế hoạch qua SQL Server Profiler hoặc bằng cách kiểm tra bộ đệm kế hoạch.

Phương pháp 1 - Sử dụng SQL Server Management Studio

SQL Server đi kèm với một số tính năng gọn gàng giúp bạn dễ dàng nắm bắt kế hoạch thực hiện, chỉ cần đảm bảo rằng mục menu "Bao gồm thực thi kế hoạch thực tế" (được tìm thấy trong menu "Truy vấn") được đánh dấu và chạy truy vấn của bạn như bình thường .

Bao gồm mục menu Kế hoạch thực hiện hành động

Nếu bạn đang cố gắng để có được kế hoạch thực hiện cho các câu lệnh trong một thủ tục được lưu trữ thì bạn nên thực hiện thủ tục được lưu trữ, như vậy:

exec p_Example 42

Khi truy vấn của bạn hoàn tất, bạn sẽ thấy một tab bổ sung có tên "Kế hoạch thực hiện" xuất hiện trong khung kết quả. Nếu bạn đã chạy nhiều báo cáo thì bạn có thể thấy nhiều gói được hiển thị trong tab này.

Ảnh chụp màn hình của Kế hoạch thực hiện

Từ đây, bạn có thể kiểm tra kế hoạch thực hiện trong SQL Server Management Studio hoặc nhấp chuột phải vào kế hoạch và chọn "Lưu kế hoạch thực hiện dưới dạng ..." để lưu kế hoạch vào một tệp ở định dạng XML.

Phương pháp 2 - Sử dụng tùy chọn SHOWPLAN

Phương pháp này rất giống với phương pháp 1 (thực tế đây là những gì SQL Server Management Studio thực hiện), tuy nhiên tôi đã đưa nó vào để hoàn thiện hoặc nếu bạn không có sẵn SQL Server Management Studio.

Trước khi bạn chạy truy vấn của mình, hãy chạy một trong các câu lệnh sau. Câu lệnh phải là câu lệnh duy nhất trong lô, tức là bạn không thể thực thi câu lệnh khác cùng một lúc:

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

Đây là các tùy chọn kết nối và vì vậy bạn chỉ cần chạy nó một lần cho mỗi kết nối. Từ thời điểm này, tất cả các câu lệnh chạy sẽ được kèm theo một tập kết quả bổ sung có chứa kế hoạch thực hiện của bạn ở định dạng mong muốn - chỉ cần chạy truy vấn của bạn như bình thường để xem kế hoạch.

Khi bạn đã hoàn tất, bạn có thể tắt tùy chọn này bằng câu lệnh sau:

SET <<option>> OFF

So sánh các định dạng kế hoạch thực hiện

Trừ khi bạn có một ưu tiên mạnh mẽ, khuyến nghị của tôi là sử dụng STATISTICS XMLtùy chọn này. Tùy chọn này tương đương với tùy chọn "Bao gồm kế hoạch thực thi thực tế" trong SQL Server Management Studio và cung cấp nhiều thông tin nhất ở định dạng thuận tiện nhất.

  • SHOWPLAN_TEXT - Hiển thị một kế hoạch thực hiện ước tính dựa trên văn bản cơ bản, mà không thực hiện truy vấn
  • SHOWPLAN_ALL - Hiển thị một kế hoạch thực hiện ước tính dựa trên văn bản với các ước tính chi phí, mà không thực hiện truy vấn
  • SHOWPLAN_XML- Hiển thị một kế hoạch thực hiện ước tính dựa trên XML với các ước tính chi phí, mà không thực hiện truy vấn. Điều này tương đương với tùy chọn "Hiển thị kế hoạch thực hiện ước tính ..." trong SQL Server Management Studio.
  • STATISTICS PROFILE - Thực hiện truy vấn và hiển thị một văn bản dựa trên kế hoạch thực hiện.
  • STATISTICS XML- Thực hiện truy vấn và hiển thị kế hoạch thực hiện thực tế dựa trên XML. Điều này tương đương với tùy chọn "Bao gồm kế hoạch thực hiện thực tế" trong SQL Server Management Studio.

Phương pháp 3 - Sử dụng SQL Server Profiler

Nếu bạn không thể chạy truy vấn của mình trực tiếp (hoặc truy vấn của bạn không chạy chậm khi bạn thực hiện trực tiếp - hãy nhớ rằng chúng tôi muốn một kế hoạch truy vấn hoạt động kém), thì bạn có thể nắm bắt một kế hoạch bằng cách sử dụng theo dõi SQL Server Profiler. Ý tưởng là để chạy truy vấn của bạn trong khi một dấu vết đang nắm bắt một trong những sự kiện "Showplan" đang chạy.

Lưu ý rằng tùy thuộc vào tải, bạn có thể sử dụng phương pháp này trên môi trường sản xuất, tuy nhiên rõ ràng bạn nên thận trọng. Các cơ chế lược tả SQL Server được thiết kế để giảm thiểu tác động lên cơ sở dữ liệu nhưng điều này không có nghĩa là sẽ không có bất kỳ tác động hiệu suất nào . Bạn cũng có thể gặp vấn đề khi lọc và xác định kế hoạch chính xác trong dấu vết của mình nếu cơ sở dữ liệu của bạn đang được sử dụng nhiều. Bạn rõ ràng nên kiểm tra với DBA của bạn để xem họ có hài lòng với bạn khi làm điều này trên cơ sở dữ liệu quý giá của họ không!

  1. Mở SQL Server Profiler và tạo một dấu vết mới kết nối với cơ sở dữ liệu mong muốn mà bạn muốn ghi lại dấu vết đó.
  2. Trong tab "Lựa chọn sự kiện", chọn "Hiển thị tất cả các sự kiện", kiểm tra hàng "Hiệu suất" -> "Showplan XML" và chạy theo dõi.
  3. Trong khi dấu vết đang chạy, hãy làm bất cứ điều gì bạn cần làm để có được truy vấn chạy chậm để chạy.
  4. Đợi cho truy vấn hoàn thành và dừng theo dõi.
  5. Để lưu dấu vết, nhấp chuột phải vào gói xml trong SQL Server Profiler và chọn "Trích xuất dữ liệu sự kiện ..." để lưu kế hoạch vào tệp ở định dạng XML.

Gói bạn nhận được tương đương với tùy chọn "Bao gồm Kế hoạch thực hiện thực tế" trong SQL Server Management Studio.

Phương pháp 4 - Kiểm tra bộ đệm truy vấn

Nếu bạn không thể chạy truy vấn của mình trực tiếp và bạn cũng không thể nắm bắt được dấu vết hồ sơ thì bạn vẫn có thể có được một kế hoạch ước tính bằng cách kiểm tra bộ đệm của kế hoạch truy vấn SQL.

Chúng tôi kiểm tra bộ đệm của kế hoạch bằng cách truy vấn DMV của SQL Server . Sau đây là một truy vấn cơ bản sẽ liệt kê tất cả các gói truy vấn được lưu trong bộ nhớ cache (dưới dạng xml) cùng với văn bản SQL của chúng. Trên hầu hết các cơ sở dữ liệu, bạn cũng sẽ cần thêm các mệnh đề lọc bổ sung để lọc kết quả xuống chỉ các kế hoạch bạn quan tâm.

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)

Thực hiện truy vấn này và nhấp vào kế hoạch XML để mở kế hoạch trong một cửa sổ mới - nhấp chuột phải và chọn "Lưu kế hoạch thực hiện dưới dạng ..." để lưu kế hoạch vào tệp ở định dạng XML.

Ghi chú:

Vì có rất nhiều yếu tố liên quan (từ lược đồ bảng và chỉ mục cho đến dữ liệu được lưu trữ và thống kê bảng), bạn nên luôn cố gắng có được một kế hoạch thực hiện từ cơ sở dữ liệu mà bạn quan tâm (thông thường là một trong số đó đang trải qua hiệu suất vấn đề).

Bạn không thể nắm bắt một kế hoạch thực hiện cho các thủ tục lưu trữ được mã hóa.

kế hoạch thực hiện "thực tế" so với "ước tính"

Một kế hoạch thực hiện thực tế là một trong đó SQL Server thực sự chạy truy vấn, trong khi đó một kế hoạch thực hiện ước tính SQL Server sẽ thực hiện những gì nó sẽ làm mà không cần thực hiện truy vấn. Mặc dù tương đương về mặt logic, một kế hoạch thực hiện thực tế hữu ích hơn nhiều vì nó chứa các chi tiết và thống kê bổ sung về những gì thực sự đã xảy ra khi thực hiện truy vấn. Điều này rất cần thiết khi chẩn đoán các vấn đề trong đó ước tính Máy chủ SQL bị tắt (chẳng hạn như khi hết số liệu thống kê).

Làm cách nào để diễn giải một kế hoạch thực hiện truy vấn?

Đây là một chủ đề đủ xứng đáng cho một cuốn sách (miễn phí) theo đúng nghĩa của nó.

Xem thêm:


8
Một lưu ý cho những người đọc trong tương lai: đặt SET STATISTICS XML ONant vào đầu truy vấn và SET STATISTICS XML OFF|ONcác khu vực xung quanh bạn không muốn hiển thị trong đầu ra của kế hoạch: Tôi thấy điều này hữu ích khi truy vấn chứa một lần lặp (WHILE) mà bạn không muốn / cần để xem trong kế hoạch thực hiện (nếu không, nó sẽ quá nặng và lâu để SQL SERVER hiển thị nó).
Roimer

2
@MonsterMMORPG bạn có thể sử dụng phương pháp 4 và sau đó CHỌN nó. Ví dụ: bằng cách sử dụng <a href=" github.com/StackExchange/dapper-dot-net"> Dapper.net </ Thẻ > kết nối ) CROSS ỨNG DỤNG sys.dm_exec_query_plan (plan_handle) WHERE TEXT THÍCH N '% Truy vấn ban đầu của bạn đi ở đây%' "); Các% là nếu bạn chỉ sử dụng một tập hợp con của truy vấn của bạn.
đánh dấu

2
@Justin phiên bản thứ 2 của cuốn sách bạn liên kết đến, để diễn giải kế hoạch thực hiện truy vấn, có niên đại từ năm 2009. Bạn vẫn sẽ nói rằng đó là một tài nguyên thực sự tốt cho mục đích đó trong năm 2016?
Abdul

3
@Abdul Cùng một tác giả, Grant Fritchey, có một cuốn sách mới hơn có tên SQL Server Query Performance Tune bao gồm các phiên bản mới hơn của SQL Server.
thelem

42

Ngoài câu trả lời toàn diện đã được đăng đôi khi rất hữu ích khi có thể truy cập kế hoạch thực hiện theo chương trình để trích xuất thông tin. Mã ví dụ cho điều này là dưới đây.

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

StartCaptureĐịnh nghĩa ví dụ

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Định nghĩa ví dụ

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

Giả sử bạn đang sử dụng Microsoft SQL Server Management Studio

  • Đối với Gói truy vấn ước tính, bạn có thể nhấn Ctrl + L hoặc nút sau.

nhập mô tả hình ảnh ở đây

  • Đối với Gói truy vấn thực tế , bạn có thể nhấn Ctrl + M hoặc nút sau đây trước khi thực hiện truy vấn.

nhập mô tả hình ảnh ở đây

  • Đối với Gói truy vấn trực tiếp , (chỉ trong SSMS 2016) sử dụng nút sau trước khi thực hiện truy vấn.

nhập mô tả hình ảnh ở đây


15

Bên cạnh các phương thức được mô tả trong các câu trả lời trước đó, bạn cũng có thể sử dụng trình xem kế hoạch thực hiện miễn phí và công cụ tối ưu hóa truy vấn ApexQuery Plan (mà gần đây tôi đã gặp phải).

Bạn có thể cài đặt và tích hợp ApexQuery Plan vào SQL Server Management Studio, vì vậy các kế hoạch thực hiện có thể được xem trực tiếp từ SSMS.

Xem các kế hoạch thực hiện dự kiến ​​trong ApexQuery Plan

  1. Nhấp vào nút Truy vấn mới trong SSMS và dán văn bản truy vấn vào cửa sổ văn bản truy vấn. Nhấp chuột phải và chọn tùy chọn Kế hoạch thực hiện ước tính của màn hình hiển thị trên màn hình từ menu ngữ cảnh.

Nút truy vấn mới trong SSMS

  1. Các sơ đồ kế hoạch thực hiện sẽ được hiển thị tab Kế hoạch thực hiện trong phần kết quả. Tiếp theo, nhấp chuột phải vào kế hoạch thực hiện và trong menu ngữ cảnh, chọn tùy chọn Mở rộng trong ApexSQL Plan.

Kế hoạch thực hiện

  1. Kế hoạch thực hiện ước tính sẽ được mở trong ApexQuery Plan và nó có thể được phân tích để tối ưu hóa truy vấn.

Kế hoạch thực hiện dự kiến

Xem các kế hoạch thực hiện thực tế trong ApexSQL Plan

Để xem kế hoạch thực hiện thực tế của một truy vấn, hãy tiếp tục từ bước thứ 2 được đề cập trước đó, nhưng bây giờ, khi kế hoạch Ước tính được hiển thị, hãy nhấp vào nút Act Actual từ thanh ruy băng chính trong ApexQuery Plan.

nhấp vào nút thực tế trên mạng từ thanh ruy băng chính

Sau khi nhấp vào nút Thực tế của Cấm, kế hoạch thực hiện thực tế sẽ được hiển thị với bản xem trước chi tiết của các tham số chi phí cùng với dữ liệu kế hoạch thực hiện khác.

Kế hoạch thực hiện

Thông tin thêm về xem kế hoạch thực hiện có thể được tìm thấy bằng cách theo liên kết này .


14

Công cụ yêu thích của tôi để có được và phân tích sâu các kế hoạch thực hiện truy vấn là SQL Sentry Plan Explorer . Nó thân thiện với người dùng, thuận tiện và toàn diện hơn cho việc phân tích chi tiết và trực quan hóa các kế hoạch thực hiện so với SSMS.

Dưới đây là một ảnh chụp màn hình mẫu để bạn có ý tưởng về chức năng nào được cung cấp bởi công cụ:

Chụp màn hình cửa sổ SQL Sentry Plan Explorer

Đây chỉ là một trong những khung nhìn có sẵn trong công cụ. Lưu ý một tập hợp các tab ở dưới cùng của cửa sổ ứng dụng, cho phép bạn nhận được các loại khác nhau của biểu diễn kế hoạch thực hiện và thông tin bổ sung hữu ích.

Ngoài ra, tôi đã không nhận thấy bất kỳ giới hạn nào của phiên bản miễn phí của nó ngăn chặn việc sử dụng nó hàng ngày hoặc buộc bạn phải mua phiên bản Pro. Vì vậy, nếu bạn thích gắn bó với phiên bản miễn phí, không có gì cấm bạn làm như vậy.

CẬP NHẬT: (Cảm ơn Martin Smith ) Plan Explorer hiện miễn phí! Xem http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view để biết chi tiết.


1
Ai đã nói về các công cụ của bên thứ ba?
basher

12
@basher: OP đã không giới hạn phương tiện với các công cụ MS hoặc bằng cách nào đó. Vậy điều gì khiến bạn nghĩ rằng một câu trả lời liên quan đến công cụ của bên thứ ba là không phù hợp?
Alexander Abakumov

3
Chỉ đùa giỡn với cách bạn bắt đầu câu trả lời Speaking of third-party toolskhi không ai đề cập đến các công cụ của bên thứ ba.
basher

4
@basher: Ồ, bắt đẹp quá! Cảm ơn bạn! Tôi đã viết lại câu trả lời của mình. Xin vui lòng cung cấp một thông tin phản hồi và / hoặc upvote nó nếu bạn muốn.
Alexander Abakumov


7

Các kế hoạch truy vấn có thể được lấy từ phiên Sự kiện mở rộng thông qua query_post_execution_showplansự kiện. Đây là một phiên XEvent mẫu:

/*
    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

Sau khi bạn tạo phiên, (trong SSMS), hãy vào Object Explorer và đi sâu vào Quản lý | Sự kiện mở rộng | Phiên. Nhấp chuột phải vào phiên "GetExecutPlan" và khởi động nó. Nhấp chuột phải vào nó một lần nữa và chọn "Xem dữ liệu trực tiếp".

Tiếp theo, mở một cửa sổ truy vấn mới và chạy một hoặc nhiều truy vấn. Đây là một cho 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

Sau một hoặc hai phút, bạn sẽ thấy một số kết quả trong tab "GetExecutPlan: Live Data". Nhấp vào một trong các sự kiện query_post_execut_showplan trong lưới và sau đó nhấp vào tab "Kế hoạch truy vấn" bên dưới lưới. Nó sẽ trông giống như thế này:

nhập mô tả hình ảnh ở đây

EDIT : Mã XEvent và ảnh chụp màn hình được tạo từ SQL / SSMS 2012 w / SP2. Nếu bạn đang sử dụng SQL 2008 / R2, bạn thể điều chỉnh tập lệnh để chạy tập lệnh. Nhưng phiên bản đó không có GUI, vì vậy bạn phải trích xuất XML showplan, lưu nó dưới dạng tệp * .sqlplan và mở nó trong SSMS. Đó là cồng kềnh. XE không tồn tại trong SQL 2005 hoặc sớm hơn. Vì vậy, nếu bạn không tham gia SQL 2012 trở lên, tôi thực sự muốn đề xuất một trong những câu trả lời khác được đăng ở đây.


5

Bắt đầu từ SQL Server 2016+, tính năng Store Store đã được giới thiệu để theo dõi hiệu suất. Nó cung cấp cái nhìn sâu sắc về lựa chọn kế hoạch truy vấn và hiệu suất. Nó không phải là sự thay thế hoàn toàn của dấu vết hoặc các sự kiện mở rộng, nhưng khi nó phát triển từ phiên bản này sang phiên bản khác, chúng tôi có thể có được một cửa hàng truy vấn đầy đủ chức năng trong các bản phát hành trong tương lai từ SQL Server. Luồng chính của Kho lưu trữ truy vấn

  1. Các thành phần hiện có của SQL Server tương tác với kho lưu trữ truy vấn bằng cách sử dụng Trình quản lý cửa hàng truy vấn.
  2. Trình quản lý cửa hàng truy vấn xác định Cửa hàng nào sẽ được sử dụng và sau đó chuyển thực thi đến cửa hàng đó (Chỉ số kế hoạch hoặc thời gian chạy hoặc thống kê chờ truy vấn)
    • Kế hoạch lưu trữ - Duy trì thông tin kế hoạch thực hiện
    • Runtime Stats Store - Duy trì thông tin thống kê thực hiện
    • Truy vấn thống kê cửa hàng thống kê - Thông tin thống kê chờ liên tục.
  3. Plan, Stats Runtime và Wait store sử dụng Query Store như một phần mở rộng cho SQL Server.

nhập mô tả hình ảnh ở đây

  1. Kích hoạt Cửa hàng Truy vấn : Cửa hàng Truy vấn hoạt động ở cấp cơ sở dữ liệu trên máy chủ.

    • Cửa hàng truy vấn không hoạt động cho cơ sở dữ liệu mới theo mặc định.
    • Bạn không thể kích hoạt kho lưu trữ truy vấn cho chủ hoặc tempdbcơ sở dữ liệu.
    • DMV có sẵn

      sys.database_query_store_options (Giao dịch-SQL)

  2. Thu thập thông tin trong Cửa hàng truy vấn : Chúng tôi thu thập tất cả thông tin có sẵn từ ba cửa hàng bằng cách sử dụng DMV của Cửa hàng truy vấn (Chế độ xem quản lý dữ liệu).

    • Lưu trữ kế hoạch truy vấn: Duy trì thông tin kế hoạch thực hiện và có thể chịu trách nhiệm cho việc nắm bắt tất cả thông tin có liên quan đến việc biên dịch truy vấn.

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

    • Cửa hàng thống kê thời gian chạy: Duy trì thông tin thống kê thực hiện và có lẽ đây là cửa hàng được cập nhật thường xuyên nhất. Những thống kê này đại diện cho dữ liệu thực hiện truy vấn.

      sys.query_store_runtime_stats (Giao dịch-SQL)

    • Truy vấn thống kê cửa hàng thống kê: Duy trì và nắm bắt thông tin thống kê chờ.

      sys.query_store_wait_stats (Giao dịch-SQL)

LƯU Ý: Kho lưu trữ thống kê truy vấn chỉ khả dụng trong SQL Server 2017+


4

Giống như với SQL Server Management Studio (đã được giải thích), Datagrip cũng có thể được giải thích ở đây .

  1. Bấm chuột phải vào một câu lệnh SQL và chọn Giải thích kế hoạch.
  2. Trong ngăn đầu ra, bấm Plan.
  3. Theo mặc định, bạn thấy biểu diễn cây của truy vấn. Để xem gói truy vấn, nhấp vào biểu tượng Hiển thị trực quan hoặc nhấn Ctrl + Shift + Alt + U

3

Đây là một điều quan trọng cần biết ngoài những điều đã nói trước đây.

Các kế hoạch truy vấn thường quá phức tạp để được biểu diễn bằng loại cột XML dựng sẵn có giới hạn 127 cấp độ của các phần tử lồng nhau. Đó là một trong những lý do tại sao sys.dm_exec_query_plan có thể quay lại NULLhoặc thậm chí gây ra lỗi trong các phiên bản MS SQL trước đó, vì vậy nói chung sẽ an toàn hơn khi sử dụng sys.dm_execigin_query_plan . Loại thứ hai cũng có một tính năng thưởng hữu ích là chọn gói cho một tuyên bố cụ thể thay vì toàn bộ lô. Đây là cách bạn sử dụng nó để xem các gói cho các báo cáo hiện đang chạy:

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

Tuy nhiên, cột văn bản trong bảng kết quả không tiện dụng lắm so với cột XML. Để có thể nhấp vào kết quả sẽ được mở trong một tab riêng dưới dạng sơ đồ, mà không phải lưu nội dung của nó vào tệp, bạn có thể sử dụng một mẹo nhỏ (hãy nhớ rằng bạn không thể chỉ sử dụng CAST(... AS XML)), mặc dù điều này sẽ chỉ hoạt động cho một hàng đơn:

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

2

Như tôi đã giải thích trong bài viết này , có hai loại kế hoạch thực hiện mà bạn có thể nhận được khi sử dụng SQL Server.

Kế hoạch thực hiện dự kiến

Kế hoạch thực hiện ước tính được tạo bởi Trình tối ưu hóa mà không chạy truy vấn SQL.

Để có được kế hoạch thực hiện ước tính, bạn cần kích hoạt SHOWPLAN_ALLcài đặt trước khi thực hiện truy vấn.

THIẾT LẬP SHOWPLAN_ALL TRÊN

Bây giờ, khi thực hiện truy vấn SQL sau:

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 sẽ tạo kế hoạch thực hiện ước tính sau:

| 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                 |

Sau khi chạy truy vấn, chúng tôi quan tâm đến việc nhận kế hoạch thực hiện ước tính, bạn cần phải vô hiệu hóa SHOWPLAN_ALL, nếu không, phiên cơ sở dữ liệu hiện tại sẽ chỉ tạo kế hoạch thực hiện ước tính thay vì thực hiện các truy vấn SQL được cung cấp.

SET SHOWPLAN_ALL OFF

Kế hoạch ước tính của SQL Server Management Studio

Trong ứng dụng SQL Server Management Studio, bạn có thể dễ dàng nhận được kế hoạch thực hiện ước tính cho bất kỳ truy vấn SQL nào bằng cách nhấn CTRL+Lphím tắt.

nhập mô tả hình ảnh ở đây

Kế hoạch thực hiện

Kế hoạch thực thi SQL thực tế được Trình tối ưu hóa tạo ra khi chạy truy vấn SQL. Nếu thống kê bảng cơ sở dữ liệu là chính xác, kế hoạch thực tế sẽ không khác biệt đáng kể so với kế hoạch ước tính.

Để có được kế hoạch thực hiện thực tế trên SQL Server, bạn cần kích hoạt các STATISTICS IO, TIME, PROFILEcài đặt, như được minh họa bằng lệnh SQL sau:

SET STATISTICS IO, TIME, PROFILE ON

Bây giờ, khi chạy truy vấn trước đó, SQL Server sẽ tạo kế hoạch thực hiện sau:

| 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.

Sau khi chạy truy vấn, chúng tôi quan tâm đến việc nhận kế hoạch thực hiện thực tế, bạn cần phải tắt các STATISTICS IO, TIME, PROFILE ONcài đặt như thế này:

SET STATISTICS IO, TIME, PROFILE OFF

Kế hoạch thực tế của SQL Server Management Studio

Trong ứng dụng SQL Server Management Studio, bạn có thể dễ dàng nhận được kế hoạch thực hiện ước tính cho bất kỳ truy vấn SQL nào bằng cách nhấn CTRL+Mphím tắt.

nhập mô tả hình ảnh ở đây

Để biết thêm chi tiết về cách nhận kế hoạch thực hiện khi sử dụng SQL Server, hãy xem bài viết này .


2

Bạn cũng có thể thực hiện điều đó thông qua powershell bằng cách sử dụng SET STATISTICS XML ON để có được kế hoạch thực tế. Tôi đã viết nó để nó hợp nhất các kế hoạch đa tuyên bố thành một kế hoạch;

    ########## 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()

0

Giải thích kế hoạch thực hiện có thể rất chi tiết và chiếm khá nhiều thời gian đọc, nhưng tóm lại nếu bạn sử dụng 'giải thích' trước truy vấn, nó sẽ cung cấp cho bạn rất nhiều thông tin bao gồm cả phần nào được thực hiện trước và vì vậy. Nếu bạn muốn đọc thêm một chút chi tiết về điều này, tôi đã biên soạn một blog nhỏ về điều này, điều này cũng chỉ cho bạn những người giới thiệu phù hợp. https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.