Sql-Server-2017

這個查詢來自哪裡?

  • May 25, 2018

我在 SQL 2017 上啟用了查詢儲存,並且我看到在SELECT *特定表上經常發生的查詢。

我想縮小這個請求的來源,看看我們是否能找到比SELECT *.

當然,我有一個來自 Query Store 的查詢 ID。我最近還要求我的開發人員在他們的連接字元串中包含應用程序名稱,許多人都這樣做了。

有沒有辦法(例如,可能使用 DMV)可以找到與此查詢關聯的應用程序名稱?

查詢查詢儲存 DMV 以獲取查詢雜湊,然後在擴展事件會話中使用該查詢雜湊來擷取相關詳細資訊。

這應該可以幫助您:

SELECT qsq.query_hash
   , qsqt.query_sql_text
FROM sys.query_store_query qsq
   INNER JOIN sys.query_store_query_text qsqt ON qsq.query_text_id = qsqt.query_text_id
WHERE qsqt.query_sql_text LIKE '%some-pertinent-SQL%';

在上面的查詢中,我有LIKE '%some-pertinent-SQL%'- 這限制了查詢的結果以匹配您正在尋找的目標 - 您需要將 替換some-pertinent-SQL為您的目標查詢的唯一部分。

query_hash在擴展事件會話定義中使用上面返回的列中的值:

CREATE EVENT SESSION [t] ON SERVER 
ADD EVENT sqlserver.sql_statement_completed(
   ACTION(sqlserver.client_app_name
   , sqlserver.client_hostname
   , sqlserver.nt_username
   , sqlserver.plan_handle
   , sqlserver.query_hash)
   WHERE ([sqlserver].[query_hash]=(0x00000000))
   )
ADD TARGET package0.ring_buffer
WITH (STARTUP_STATE=OFF);
GO

將 替換0x00000000為實際的查詢雜湊值。

使用以下命令啟動擴展事件會話:

ALTER EVENT SESSION [t] ON SERVER 
STATE = START;

右鍵點擊對象資源管理器中的擴展事件會話以查看有關客戶端主機名、使用者名等的詳細資訊,以便在查詢發生時進行查詢。

在此處輸入圖像描述

為了測試這一點,我在我的 SQL Server 2016 測試實例上執行了以下程式碼:

CREATE DATABASE QueryStoreTest
ON PRIMARY 
(
     NAME = QueryStoreTest_primary
   , FILENAME = 'C:\temp\QueryStoreTest_primary.mdf'
   , SIZE = 100MB
   , FILEGROWTH = 100MB
   , MAXSIZE = 1000MB
)
LOG ON 
(
     NAME = QueryStoreTest_log
   , FILENAME = 'C:\temp\QueryStoreTest_log.ldf'
   , SIZE = 100MB
   , FILEGROWTH = 100MB
   , MAXSIZE = 1000MB
);
GO
ALTER DATABASE QueryStoreTest 
SET QUERY_STORE = ON;

在這裡,我將在 QueryStoreTest 數據庫中創建幾個對象和一個測試查詢:

USE QueryStoreTest;
CREATE TABLE dbo.qst
(
   id int NOT NULL
       PRIMARY KEY CLUSTERED
       IDENTITY(1,1)
);

CREATE TABLE dbo.qst2
(
   id int NOT NULL
       PRIMARY KEY CLUSTERED
       IDENTITY(1,1)
);

SELECT *
/*  test query store query  */
FROM dbo.qst
   LEFT MERGE JOIN dbo.qst2 on qst.id = qst2.id;

在這裡,我將從查詢儲存中獲取查詢雜湊:

SELECT qsq.query_hash
   , qsqt.query_sql_text
FROM sys.query_store_query qsq
   INNER JOIN sys.query_store_query_text qsqt ON qsq.query_text_id = qsqt.query_text_id
WHERE qsqt.query_sql_text LIKE '%test query store query%';

結果:

╔════════════════════╦════════════════════════════════════════════════════════╗
║ query_hash ║ query_sql_text ║
╠════════════════════╬════════════════════════════════════════════════════════╣
║ 0x3A0100223AD74766 ║ SELECT * /* 測試查詢儲存查詢 */ FROM dbo.qst ║
║ ║ 左合併加入 dbo.qst2 on qst.id = qst2.id ║
╚════════════════════╩════════════════════════════════════════════════════════╝

現在,我將創建擴展事件會話:

CREATE EVENT SESSION [t] ON SERVER 
ADD EVENT sqlserver.sql_statement_completed
(
   ACTION (
         sqlserver.client_app_name
       , sqlserver.client_hostname
       , sqlserver.nt_username
       , sqlserver.plan_handle
       , sqlserver.query_hash
   )
   WHERE ([sqlserver].[query_hash]=(0x3A0100223AD74766))
)
ADD TARGET package0.ring_buffer
WITH (STARTUP_STATE=OFF)
GO

並開始會話:

ALTER EVENT SESSION [t] ON SERVER 
STATE = START;

現在,如果我執行測試查詢並查看會話中的實時數據,我會看到:

在此處輸入圖像描述

清理:

USE master;
GO
ALTER EVENT SESSION [t] ON SERVER 
STATE = STOP;
GO
DROP EVENT SESSION [t] ON SERVER;
GO
ALTER DATABASE QueryStoreTest SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE QueryStoreTest;

引用自:https://dba.stackexchange.com/questions/207684