相同的查询 - 查询存储中的不同查询

vid*_*jot 5 sql sql-server entity-framework azure-sql-database sql-query-store

问题:

我们使用实体框架(6.21)作为我们的 ORM 管理器。我们的数据库是Azure Sql 数据库。

因为某些参数化查询(在我们的应用程序中经常使用)在某些输入上运行速度很慢(在某些输入上运行 60 秒,在其他输入上运行 0.4 秒)

我们开始使用 MS SQL Management Studio 中的 QueryStore 和 QueryStore 资源管理器(MSSMS -> 对象资源管理器 -> 查询存储)调查这些查询。

我们发现,QueryStore 将两个相同的(相同的 sql 查询但不同的参数 - 参数甚至没有存储)查询存储为不同的查询(具有不同的query_id)。通过不同的查询,我的意思是表中的不同行 sys.query_store_query)。

我通过查看 QueryStore 表来检查这一点:

    SELECT 
     qStore.query_id,
     qStore.query_text_id,
     queryTextStore.query_sql_text
     ROW_NUMBER() OVER(PARTITION BY query_sql_text ORDER BY query_sql_text ASC) AS rn 
    FROM 
    sys.query_store_query qStore
    INNER JOIN 
    sys.query_store_query_text queryTextStore 
    ON qStore.query_text_id = queryTextStore.query_text_id
Run Code Online (Sandbox Code Playgroud)

截图来自MSSSM

我无法在 MSSMS 中轻松比较这些查询的计划,因为每个查询都有其自己的关联计划。

预期行为: 我假设每次后续运行具有不同参数的相同查询都会导致:

1/ 重新使用现有计划或

2/根据传递的参数值创建另一个计划......

例子:

查询看起来像这样(实际上查询要复杂得多,因为它们是由 EntityFramework 生成的):

SELECT * FROM tbl WHERE a = @__plinq__
Run Code Online (Sandbox Code Playgroud)

并且它的两次后续运行(具有不同的参数)将导致sys.query_store_query.

问题:

如何使 Azure 将查询与相同的文本保存为相同的查询?或者我错过了什么或者这是预期的行为?

或者更一般地说,如果数据库查询是由实体框架生成的,如何调整数据库查询?

SQL Server 查询存储如何认为两个查询相同或不同?

编辑1:更新

基于@PeterB评论(在调用表值函数时添加查询提示),我们能够通过对某些参数值进行缓慢查询来解决问题(我们"recompile"在有问题的查询上添加了提示)。

基于@GrantFritchey 提示,我检查了 context_settings,但query_store表中仍然有多行具有相同query_sql_text和相同context_settings_id但不同的行query_id

那么我们仍然想知道SQL Server查询存储如何认为两个查询相同或不同?

Mio*_*gRd 3

对于不同的查询条目,查询存储用于查询的键包括:

  • 查询文本 ID,
  • 上下文设置id,
  • 对象 ID,
  • 批处理SQL句柄,
  • 查询参数化类型

如果其中任何一个与查询不同,它将在查询表中生成一个新条目。请注意,batch_sql_handle 仅针对引用临时表的查询填充。因此,您可以检查哪些值对于您列出的查询是不同的。

目前没有任何设置可以控制查询存储聚合查询的方式。使其将它们视为相同的唯一方法是更改​​您的工作负载,以便上面列出的字段匹配。但也许更好的方法是您编写自己的报告查询,该查询将根据您的需要聚合查询及其统计信息。