要回答您的第一个问题,NHibernate 不处理执行计划。SQL Server 处理执行计划。如果 NHibernate 生成的动态 SQL 是参数化的,则计划将被归类为“已准备”并且将被重用,假设在每个后续执行中提供的参数可以生成相同的优化查询计划。如果动态 SQL 没有参数化,则执行计划将被归类为“Adhoc”,仍然可以重用。
我使用这段 T-SQL 来监控各种查询计划的缓存大小。我相信我是从 Paul Randal 的网站 (http://www.sqlskills.com/BLOGS/PAUL/) 复制的,但时间太长了,我无法确定。
SELECT
objtype AS [CacheType],
count_big(*) AS [Total Plans],
sum(cast(size_in_bytes as decimal(12,2)))/1024/1024 AS [Total MBs],
avg(usecounts) AS [Avg Use Count],
sum(cast((CASE WHEN usecounts = 1 THEN size_in_bytes ELSE 0 END) as decimal(12,2)))/1024/1024 AS [Total MBs - USE Count 1],
sum(CASE WHEN usecounts = 1 THEN 1 ELSE 0 END) AS [Total Plans - USE Count 1]
FROM sys.dm_exec_cached_plans
GROUP BY objtype
ORDER BY [Total MBs - USE Count 1] DESC;
GO
要回答您的第一个问题,NHibernate 不处理执行计划。SQL Server 处理执行计划。如果 NHibernate 生成的动态 SQL 是参数化的,则计划将被归类为“已准备”并且将被重用,假设在每个后续执行中提供的参数可以生成相同的优化查询计划。如果动态 SQL 没有参数化,则执行计划将被归类为“Adhoc”,仍然可以重用。
我使用这段 T-SQL 来监控各种查询计划的缓存大小。我相信我是从 Paul Randal 的网站 (http://www.sqlskills.com/BLOGS/PAUL/) 复制的,但时间太长了,我无法确定。
ORM 本身通常不是问题,而是它们的使用方式。SQL Server 生成执行计划。NHibernate 可以生成导致 SQL 生成错误执行计划的查询。如果您在查询中使用变量,则可以重用执行计划。字符串连接通常会阻止计划重用。有关更多信息,请参阅此问题。
除了已经提到的参数化问题之外,所有的 ORM 都可能导致生成非常糟糕的计划。当有很多搜索选项导致 SQL Server 查询中的 WHERE 子句非常大时,通常会执行此操作,该子句充满了 SQL Server 无法处理的 OR 语句。