当函数存在时,TSQL视图选择优化

时间:2015-01-12 16:52:27

标签: tsql ssis query-optimization

我将这个简单的SQL作为SSIS任务中的源:

Select * from budgetview

来源是:

CREATE VIEW [dbo].[BudgetView] AS
SELECT   DISTINCT  Country, 
            SDCO AS Company, 
            SDAN8 AS Customer, 
            SDLITM AS PrintableItemNumber, 
            dbo.fn_DateFromJulian(SDIVD) AS Date, 
            SDPQOR/100.0 AS Quantity, 
            SDAEXP/100.0 AS Value, 
            SDITWT/10000.0 AS Weight
FROM         dbo.F553460

索引没有建议,每件事情似乎都已优化。

函数fn_DateFromJulian源是:

CREATE FUNCTION [dbo].[fn_DateFromJulian] 
(
    @JulianDate numeric(6,0)
)
RETURNS date
AS
BEGIN
    declare @resultdate date=dateadd(year,@JulianDate/1000,'1900-01-01')
    set @resultdate=dateadd(day,@JulianDate%1000 -1,@resultdate)
    return @resultdate

END

问题在于我正在等待大约20分钟,才能让SSIS中的行进入.... SSIS task

我在开始前等待20分钟

有没有找到罪魁祸首的建议?

2 个答案:

答案 0 :(得分:3)

我的假设是通过计算Julian日期值来消耗花在视图上的时间。如果没有看到实际的查询计划,基于以下文章,这似乎是一个公平的猜测。

将原始函数重写为下面的表值函数(我只是简单地将您的代码混合在一起,可能有改进的机会)

CREATE FUNCTION dbo.fn_DateFromJulianTVF
(
    @JulianDate numeric(6,0)
)
RETURNS TABLE AS
RETURN
(
    SELECT dateadd(day,@JulianDate%1000 -1,dateadd(year,@JulianDate/1000,CAST('1900-01-01' AS date))) AS JDEDate
)

用法是

CREATE VIEW [dbo].[BudgetView] AS
SELECT   DISTINCT  Country, 
            SDCO AS Company, 
            SDAN8 AS Customer, 
            SDLITM AS PrintableItemNumber, 
            J.JDEDate AS [Date], 
            SDPQOR/100.0 AS Quantity, 
            SDAEXP/100.0 AS Value, 
            SDITWT/10000.0 AS Weight
FROM         dbo.F553460 AS T
    CROSS APPLY
        dbo.fn_DateFromJulianTVF(T.SDIVD) AS J

标量值函数,类似于代码重用的气味,像重复使用的一次性尿布一样执行

答案 1 :(得分:1)

只是检查,但我是否理解为T.SDIVD的每个唯一值只有一个唯一的函数结果值?换句话说,没有两个不同的T.SDIVD将从函数返回相同的值?

在这种情况下,这里发生的事情(恕我直言)是你首先扫描整个表,因为每个记录计算f(SDIVD)值,然后通过聚合(DISTINCT)发送整个结果集。 / p>

由于函数在MSSQL中远非最佳,我建议通过转换事件链来限制它们的使用,并按照以下方式执行:

CREATE VIEW [dbo].[BudgetView] AS
SELECT /* DISTINCT */
                Country, 
                Company, 
                Customer, 
                PrintableItemNumber, 
                dbo.fn_DateFromJulian(SDIVD) AS Date, 
                Quantity, 
                Value, 
                Weight
          FROM (

                SELECT DISTINCT Country, 
                                SDCO AS Company, 
                                SDAN8 AS Customer, 
                                SDLITM AS PrintableItemNumber, 
                                SDIVD, 
                                SDPQOR/100.0 AS Quantity, 
                                SDAEXP/100.0 AS Value, 
                                SDITWT/10000.0 AS Weight
                           FROM dbo.F553460 ) dist_F553460
               ) 

如果你有很多双重记录,这应该可以提高性能,如果你只有很少的记录,那么它就不会产生太大的影响,如果有的话。如果你知道你没有双打,你应该首先摆脱DISTINCT,因为这是导致延迟的原因!

无论如何,关于这个功能你可以添加以下技巧:

CREATE FUNCTION [dbo].[fn_DateFromJulian] 
(
    @JulianDate numeric(6,0)
)
RETURNS date
WITH SCHEMABINDING
AS
BEGIN
    declare @resultdate date=dateadd(year,@JulianDate/1000,'1900-01-01')
    set @resultdate=dateadd(day,@JulianDate%1000 -1,@resultdate)
    return @resultdate

END

WITH SCHEMABINDING会导致一些内部优化,使其执行速度稍快一些,YMMV。它有局限性,但在这里它可以很好地工作。

编辑:删除'外部'DISTINCT,因为它(可能是我的第一个假设)不需要。