joemac12 Asked: 2021-11-05 12:54:35 +0800 CST2021-11-05 12:54:35 +0800 CST 2021-11-05 12:54:35 +0800 CST 优化器如何执行标量函数 772 我在网上读到标量函数会影响性能,因为优化器无法访问标量函数的内容。由于函数是针对每一行执行的,优化器是否必须每次都为函数的内容构建一个执行计划,或者它是否在第一次访问该函数时构建该计划,然后将其用于所有其他行? sql-server optimization 2 个回答 Voted Best Answer Charlieface 2021-11-05T14:22:59+08:002021-11-05T14:22:59+08:00 对于未内联的标量 UDF,实际查询计划仅生成一次(显然假设在执行之间没有统计信息更新、索引重建或任何 DDL 更改)。该计划像任何其他查询计划一样被缓存和重用。 它不会在 中获取任何数据sys.dm_exec_query_stats,因此您无法通过这种方式获得任何统计信息。但是你可以sys.dm_exec_function_stats用来获取类似的信息。 您可以使用以下查询查看缓存的查询计划 SELECT p.objtype, OBJECT_NAME(f.object_id), st.text, qp.query_plan, p.refcounts, p.usecounts, f.execution_count FROM sys.dm_exec_function_stats f JOIN sys.dm_exec_cached_plans p ON p.plan_handle = f.plan_handle CROSS APPLY sys.dm_exec_query_plan(p.plan_handle) qp CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) st WHERE f.object_id = OBJECT_ID(N'dbo.fnTest') OPTION(RECOMPILE); 您可以使用Database Scoped ConfigurationEXEC_QUERY_STATS_FOR_SCALAR_FUNCTIONS来打开或关闭此功能(到目前为止,该旋钮仅适用于 Azure SQL DB 和托管实例)。 函数的实际执行确实发生在单独的范围内,需要对参数进行编组并前后返回结果,以及上下文切换(SET例如不同的选项和不同的局部变量范围)。这是他们表现如此糟糕的主要原因之一。 user241655 2021-11-05T14:31:22+08:002021-11-05T14:31:22+08:00 Oracle 将缓存 DETERMINISTIC 标量函数的输入值和返回值并重新使用它们以提高效率。由于这是 SQL Server,因此需要一种不同的方法。 如果您的查询为大量行调用相同的标量函数,而标量函数的输入只是几个值,则可以使用预先计算的外部表连接来提高性能。 例如,如果您的标量函数将一个人的年龄作为输入并输出一个数字作为输出,您可以 使用内联表为输入范围提供标量函数的输入和返回值 将该表加入您的主查询,而不使用标量函数
对于未内联的标量 UDF,实际查询计划仅生成一次(显然假设在执行之间没有统计信息更新、索引重建或任何 DDL 更改)。该计划像任何其他查询计划一样被缓存和重用。
它不会在 中获取任何数据
sys.dm_exec_query_stats
,因此您无法通过这种方式获得任何统计信息。但是你可以sys.dm_exec_function_stats
用来获取类似的信息。您可以使用以下查询查看缓存的查询计划
您可以使用Database Scoped Configuration
EXEC_QUERY_STATS_FOR_SCALAR_FUNCTIONS
来打开或关闭此功能(到目前为止,该旋钮仅适用于 Azure SQL DB 和托管实例)。函数的实际执行确实发生在单独的范围内,需要对参数进行编组并前后返回结果,以及上下文切换(
SET
例如不同的选项和不同的局部变量范围)。这是他们表现如此糟糕的主要原因之一。Oracle 将缓存 DETERMINISTIC 标量函数的输入值和返回值并重新使用它们以提高效率。由于这是 SQL Server,因此需要一种不同的方法。
如果您的查询为大量行调用相同的标量函数,而标量函数的输入只是几个值,则可以使用预先计算的外部表连接来提高性能。
例如,如果您的标量函数将一个人的年龄作为输入并输出一个数字作为输出,您可以