首页 > 解决方案 > 避免针对具有不同注释的相同查询的计划缓存膨胀

问题描述

启用强制参数化的 SQL Server 2017。

我们的应用服务器通过一次登录连接到数据库,因此在 SQL Profiler 中我们看不到真实用户(GUI 用户)的名称。为了查看有关 SQL 服务器级别的信息,我在 NHibernate 中定义了一个拦截器,它在每个查询的开头放置带有用户名的注释。

这解决了问题,但又产生了另一个问题:SQL Server 认为来自不同用户的相同查询是不同的,即使它已正确参数化,唯一的区别是注释。将每个计划乘以 150 会使计划缓存膨胀。

问题:我怎样才能让 SQL Server 认为这些注释查询在计划缓存的哈希方面是相同的?

由于某些遗留应用程序需要它,强制参数化选项已经处于活动状态。

将评论放在查询末尾也不起作用。在我开始尝试其他解决方案(例如创建批处理并将用户信息和实际查询放在 2 个不同的语句中)之前,也许您有一些建议如何格式化注释以避免问题。如果分析器已连接但未在活动监视器或类似工具的“活动昂贵查询”中显示用户名,则批处理黑客将起作用。

以其他方式解决原始问题的 NHibernate 特定技巧也会很棒。

提前感谢您的任何提示!

编辑 2020-06-15:我看到的唯一方法是将批处理与 2 个语句一起使用。第一个将在将 sessionid 映射到当前用户名的小表中进行更新插入。

标签: sql-servernhibernate

解决方案


文档中:

如果 Transact-SQL 语句在字面上匹配先前执行的 Transact-SQL 语句和缓存计划(每个字符一个字符),则该语句符合现有条件。

评论是查询的一部分。没有办法让查询仅因注释而不同以使用相同的查询计划。

您可以通过其他方式传输您的附加信息来实现您的目标,例如将您的用户名放在连接Application Name属性中,例如此处

应用程序名称可以在打开连接之前以编程方式设置,但这也会减少连接池中的连接重用。此应用程序名称属性在 SQL 事件探查器中可见。我已经用它来区分应用程序,这确实是它的预期用途。

据我所知,应用程序名称属性不是查询计划缓存键的一部分,因此具有不同的应用程序名称不应导致查询计划缓存未命中。但我还没有真正检查过这个。


推荐阅读