zoukankan      html  css  js  c++  java
  • SQL Server 2019 中标量用户定义函数性能的改进

    在SQL Server中,我们通常使用用户定义的函数来编写SQL查询。UDF接受参数并将结果作为输出返回。我们可以在编程代码中使用这些UDF,并且可以快速编写查询。我们可以独立于任何其他编程代码来修改UDF。

    在SQL Server中,我们具有以下类型的用户定义函数。

      1. 标量函数:标量用户定义的函数返回单个值。您将始终具有RETURNS子句。返回值不能是文本,图像或时间戳。以下是标量函数的示例。

        传统上,标量用户定义函数不被认为是高性能的好选择,但是SQL Server 2019提供了一种提高这些标量用户定义函数的性能的方法。我们将在本文的后一部分中了解更多有关它的信息。

      2. 多语句表值函数(TVF):其语法类似于标量用户定义函数,并提供多值作为输出。由于基数估计问题,这些性能也不优化。

        SQL Server 2012提供固定的基数估计,而SQL Server 2012提供的基数估计为100。SQLServer 2017使用称为交错执行的功能改进了这些MSTVF的基数估计。

    1. 内联表值函数:内联表值函数是性能优化的函数。它们不包含表定义。此函数内部的查询批处理是一条语句,因此,当我们以批处理或循环方式使用它时,它不会提供任何性能问题。

      下面是内联表值函数的示例。

    标量用户定义函数

    如上所述,标量用户定义的函数不会在SQL Server中提供性能优势。因此,在本节中,我们将首先查看标量用户定义函数的性能问题,然后使用SQL Server 2019比较性能。

    对于此示例,我正在运行SQL Server 2019 2.1和WideWorldImporters数据库。

    将数据库兼容性级别设置为140。

    使用数据库范围的配置选项清除过程缓存。这将从所有存储的执行计划或缓存中清除我们的数据库。

    现在,在WideWorldImporters数据库中创建标量用户定义函数。此函数将根据说明返回数量。执行以下脚本。

    我们可以使用类似于表列对象的功能。运行以下命令,该命令将UDF函数用作普通表列。

    在上面的屏幕截图中,您可以看到大约花了18分钟来处理228,176条记录。

    现在让我们以兼容级别150(SQL Server 2019)运行相同的查询。

    使用此已修改的兼容性级别再次运行查询。

    在SQL Server 2019中,您可以注意到查询仅用19秒完成了处理228,176行,而SQL Server 2016中则是12分钟。相对而言,处理这些结果非常快。

    现在让我们在SQL Server 2016和SQL Server 2019数据库兼容性级别中再次运行查询,并捕获统计数据IO和统计时间以及要与之进行比较的实际执行计划。

    SQL Server 2019统计信息输出

    (受影响的228176行)
    表'OrderLines'。扫描计数5,逻辑读857,物理读0,预读0,lob逻辑读180,lob物理读0,lob预读0。
    表'OrderLines'。段读取为2,段跳过0。
    表为“工作表”。扫描计数227,逻辑读730037,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
    表'Workfile'。扫描计数0,逻辑读0,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。

    (受影响的1行)

    SQL Server执行时间:
       CPU时间= 15287毫秒,经过的时间= 18782毫秒。
    SQL Server解析和编译时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。

    SQL Server执行时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。

    SQL Server 2016统计信息输出

    SQL Server解析和编译时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。
    SQL Server执行时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。
    SQL Server解析和编译时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。
    SQL Server执行时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。

    SQL Server执行时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。

    (受影响的228176行)

    表“工作表”。扫描计数0,逻辑读0,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
    表'OrderLines'。扫描计数1,逻辑读3504,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。

    (受影响的1行)

    SQL Server执行时间:
       CPU时间= 1071719 ms,经过的时间= 1109655 ms。
    SQL Server解析和编译时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。
    SQL Server执行时间:
       CPU时间= 0毫秒,经过的时间= 0毫秒。

    如果将执行级别与兼容性级别140(SQL Server 2017)和兼容性级别150(SQL Server 2019)进行比较,则可以看到CPU时间和运行时间有了显着改善。

    在下表中,您可以看到Scalar用户定义函数与SQL Server 2019的性能优化比较

    SQL Server兼容性级别140

    SQL Server兼容性级别150

    性能改进

    CPU – 1,071,719毫秒

    CPU 15,287毫秒

    1,056,432毫秒

    经过时间1,109,655毫秒

    经过时间18,782毫秒

    1,090,873毫秒

    执行计划比较

    在本节中,我们将比较在使用SQL Server 2019及更高版本运行标量UDF时的执行计划。

    以下是我们以兼容级别140(SQL Server 2017或更低版​​本)运行标量UDF时的实际执行计划

    在估算的执行计划中,我们将对此有一个更清晰的认识。在下面的计划中,它显示了查询和UDF函数的单独执行计划。因此,SQL Server在SQL Server 2017之前将标量UDF函数视为一个单独的标识。每次调用此UDF函数时,SQL Server都需要做额外的工作。

    现在,如果我们查看SQL Server 2019中的实际估计计划,我们将获得一个较早执行计划的复杂计划,如下图所示。在SQL Server 2019中,由于内联功能,它能够将UDF操作合并到单个查询计划中。

    在此执行计划中,它在下部区域显示了UDF。您可以看到多个运算符来执行查询。SQL Server 2019内联标量UDF以优化查询的执行。它不会将此UDF视为单独的标识,但是会像正常的select语句一样运行它。因此,我们获得了CPU,内存,执行时间等方面的性能优势。

    我们可以检查SQL Server是否能够内联特定标量UDF。SQL Server 2019在sys.sql_modules中引入了新列is_inlineable。运行以下查询,并在其中传递标量函数名称。在下面的查询中,我们的UDF显示值1,这意味着SQL Server 2019可以倾斜此函数。

    在SQL Server 2019中内嵌标量UDF的条件

    如果满足以下条件,则SQL Server 2019可以内联标量函数。

    1. UDF不是分区函数
    2. 没有引用任何表变量
    3. 没有使用任何计算列。
    4. 不能在Group By子句中调用UDF
    5. 可以在标量UDF中使用以下构造
      • Declare
      • Select
      • If/ else
      • Return
      • Exits or IsNull
    1. UDF没有包含任何与时间有关的函数。

    使用SQL Server 2019 UDF倾斜功能的不同方法。

    我们可以通过以下方式在SQL Server 2019中使用此UDF内联功能。

    • 将数据库兼容性级别设置为150(SQL Server 2019)
    • 我们可以使用新的数据库处理配置来控制此行为。您可以在下面的数据库作用域配置列表中看到,我们有了新的选项TSQL_SCALAR_UDF_INLINING

    • 我们还可以通过指定查询提示来禁用特定查询的标量UDF内联:

      在此示例中,我们使用以下参数禁用了UDF内联

      注意:如果我们已为标量UDF内联启用数据库作用域配置,并使用查询提示在查询级别禁用此功能,则SQL Server将优先提示数据库作用域配置或兼容性级别设置。

    • 创建标量UDF时,我们可以指定也关闭此功能。我们需要在以下示例中指定WITH INLINE = OFF

      默认情况下,在SQL Server 2019中启用了标量UDF内联,因此,我们不需要指定参数WITH INLINE = ON。如果需要,可以指定它。

    结论:

    在本文中,我们探讨了由于内联导致标量UDF的显着性能改进。这些增强功能会给开发人员和管理员带来微笑。

  • 相关阅读:
    读书
    Web前端知识体系精简
    让你分分钟理解 JavaScript 闭包
    常用 Git 命令使用教程
    js库写法
    Gitlab的使用
    appium-环境搭建(一)
    Selenium-几种等待方式
    Selenium-免登录的实现
    Selenium-百度登录简单例子
  • 原文地址:https://www.cnblogs.com/VicLiu/p/11868053.html
Copyright © 2011-2022 走看看