这个查询来自哪里?

Del*_*Lee 4 query-store sql-server-2017

我在 SQL 2017 上启用了查询存储,并且我在查询中看到频繁发生SELECT *在特定表上的查询。

我想缩小此请求的来源范围,看看我们是否可以找到比执行SELECT *.

当然,我有一个来自 Query Store 的查询 ID。我最近还要求我的开发人员在他们的连接字符串中包含应用程序名称,很多人都这样做了。

有没有办法(例如,可能使用 DMV)找出与此查询关联的应用程序名称?

Han*_*non 6

查询查询存储 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%';
Run Code Online (Sandbox Code Playgroud)

在上面的查询中,我有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
Run Code Online (Sandbox Code Playgroud)

将 替换为0x00000000实际的查询哈希值。

使用以下命令启动扩展事件会话:

ALTER EVENT SESSION [t] ON SERVER 
STATE = START;
Run Code Online (Sandbox Code Playgroud)

右键单击对象资源管理器中的扩展事件会话以查看有关客户端主机名、用户名等的详细信息,以便在发生查询时进行查询。

在此处输入图片说明

为了测试这一点,我在我的 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;
Run Code Online (Sandbox Code Playgroud)

在这里,我将在 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;
Run Code Online (Sandbox Code Playgroud)

在这里,我将从查询存储中获取查询哈希:

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%';
Run Code Online (Sandbox Code Playgroud)

结果:

?????????????????????????????????????????????????????? ?????????????????????????????????
? 查询哈希?query_sql_text ?
?????????????????????????????????????????????????????? ?????????????????????????????????
? 0x3A0100223AD74766?SELECT * /* 测试查询存储查询 */ FROM dbo.qst ?
? ? 在 qst.id = qst2.id 上左合并加入 dbo.qst2 ?
?????????????????????????????????????????????????????? ?????????????????????????????????

现在,我将创建扩展事件会话:

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
Run Code Online (Sandbox Code Playgroud)

并开始会话:

ALTER EVENT SESSION [t] ON SERVER 
STATE = START;
Run Code Online (Sandbox Code Playgroud)

现在,如果我运行测试查询并查看会话中的实时数据,我会看到:

在此处输入图片说明

清理:

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;
Run Code Online (Sandbox Code Playgroud)