使用参数化 SQL 时,SQL Server 正在缓存具有相同查询的查询计划

Min*_*him 2 sql-server

我在 SQL Server 2012 SP1 中使用参数化 SQL 查询。

参考sys.dm_exec_cached_planssys.dm_exec_query_stats,优化器似乎多次创建相同的计划,而不是重用已经存在的计划。

该服务器有很多与同一缓存计划query_hashquery_plan_hash,(目前和增加正是4700个计划)。

我的问题是:

  1. 这种情况正常吗?
  2. 为什么优化器一次又一次地创建一个已经存在的新计划?
  3. 有没有一种好方法可以强制优化器根据参数化 SQL 重用查询计划?

Bre*_*zar 10

你在这里有几个不同的问题:

问:为什么优化器一次又一次地创建一个已经存在的新计划?

这些属性都会影响计划重用:

  • 不同的数据库都有自己的计划
  • 不同的参数长度有自己的计划(特别是这个 NHibernate bug,但其他 ORM 也会出现类似的问题)
  • ANSI NULL 等不同的连接设置可以得到自己的计划
  • 不同的间距或注释可以有自己的计划(就像你的代码动态添加注释来指示查询来自哪里)

问:在参数化 SQL 方面,是否有强制优化器重用查询计划的好方法?

是的 - 考虑以上会影响计划重用的事情。显然,如果您有一个软件即服务类型的模型,其中每个客户都有自己的数据库,那么您无法真正帮助那里的事情,但您可以帮助其他两个因素。与应用程序的连接设置保持一致,不要在查询中动态注入不同的间距或注释,并确保应用程序中的数据类型与数据库中的数据类型匹配。

问:这种情况正常吗?

在现场看到并不罕见,尤其是旧的 NHibernate/EF 版本,它们根据您传入的任何参数使用不同的参数长度(如该链接中所述)。

性能症状是更高的 CPU 使用率(由于增加的查询编译)和更高的计划缓存内存使用率,但它们通常不是 SQL Server 上的最大问题。