使用Inline表值函数来封装SQL代码的性能

时间:2017-06-15 20:50:27

标签: sql-server tsql user-defined-functions

问题是:可以使用内联表值函数(ITVF)来封装和重用代码吗?或者这会导致性能问题吗?

我正在研究内联表值函数,这引出了我的讨论: When would you use a table-valued function?

讨论中的一个答案表明,内联表值函数“允许优化器处理这些函数与它们封装的对象没有什么不同,从而为您提供最佳性能(假设您的索引和统计数据是理想的)。”

我最初的问题是我试图将不同的数据源重新格式化为标准格式,然后将它们联合起来。我测试了联合6种不同的ITVF,而不是在一个查询中执行联合和转换。执行计划完全相同。

由于我的背景是oop,我宁愿将查询分成更小的函数,但在我承诺在未来的项目中执行此操作之前,我想知道使用太多的ITVF最终是否会导致性能问题。

2 个答案:

答案 0 :(得分:1)

ITVF非常适合封装查询逻辑以供重用。我有十几个财务报告,它们都查询相同的表集以获得大致相同的信息,并且通过创建提供该数据的函数,我可以确保我的所有报告都是从同一个数据体中提取的。相同的过滤器和转换等。

话虽如此,您也可以轻松创建视图而不是ITVF,但ITVF还提供了一种根据发送的参数过滤或以其他方式转换数据的方法。例如,我的财务功能可以接受某个区域name作为可选输入参数,仅返回该区域的数据。通过这种方式使用ITVF,优化器可以根据发送的参数优化查询计划,这有助于而不是阻碍性能。

我建议在六个不同的ITVF上使用联合而不是联合,只需将所有表格合并到一个ITVF中:这样,如果表格模式或报表需求发生变化,您只有一个地方可以进行更新。

答案 1 :(得分:1)

  

可以使用内联表值函数(ITVF)来封装和重用代码吗?

是。它们在多语句TVF中更胜一筹,因为使用多语句TVF,封装可以防止查询优化器将谓词推入TVF逻辑,并阻止它准确估计返回的行数。

  

或者这会导致性能问题吗?

简短回答,通常不是。

更长的答案:

有四种方法可以封装和重用查询逻辑(整个查询,而不仅仅是标量表达式)。

  1. 浏览
  2. 内联表值函数
  3. 多语句表值函数
  4. 临时表
  5. 表变量
  6. 视图和内联TVF本质上不会降低性能,但它们会增加查询优化的复杂性。

    如果优化程序无法始终如一地找到低成本计划,您可能需要进行干预。一种常见的方法是强制中间结果的假脱机(即具体化),例如用多语句TVF替换内联TVF,或者将结果预先假设为临时表。

    当在较大查询的上下文中运行时,假脱机降低了封装查询的复杂性,代价是可能优化封装查询。

    在假脱机结果时,临时表通常是最好的,因为SQL Server可以使用索引和统计信息,使SQL Server能够准确评估将消耗中间结果的计划的成本。