2015-01-12 23 views
1

我有這個簡單的SQL作爲一個SSIS任務的源:TSQL視圖選擇優化時,功能存在

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 

有索引的,每個NO意見事情似乎優化。

功能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分鐘有開始之前

有沒有任何建議找到罪魁禍首?

+1

標量是邪惡的 http://sqlblog.com/blogs/paul_white/archive/2012/09/05/compute-scalars-expressions-and-execution-plan-performance.aspx http://sqlblog.com /blogs/rob_farley/archive/2011/11/08/when-is-a-sql-function-not-a-function.aspx在我看來,理想的做法是將其轉換爲內聯表值函數,然後使用它是這樣的。可以爲你節省一些處理時間。另一件事你可以通過提示來加速第一個10k,但在這裏似乎有問題http://sqlblog.com/blogs/rob_farley/archive/2011/02/17/the-ssis-tuning-tip-that-everyone -misses.aspx – billinkc

+0

你能幫我理解你的功能嗎?看看[wiki文章](http://en.wikipedia.org/wiki/Julian_day),我應該能夠通過2451545進入函數並獲得2001-01-1,但函數只接受6位數字 – billinkc

+0

否它是這樣的:110235是2010年的第235天。我在我們的ERP中使用JDEdwards。看到這個:http://stackoverflow.com/questions/1171208/what-is-the-precise-definition-of-jdes-julian-date-format – e4rthdog

回答

2

我的假設是花費在視圖上的時間是通過計算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

只是檢查,但我在正確的瞭解,爲T.SDIVD每一個獨特的價值會有的功能只是一個獨特的結果值?換句話說,沒有兩個不同的T.SDIVD會從函數返回相同的值?在這種情況下(IMHO)發生的是你首先掃描整個表,爲每個記錄計算f(SDIVD)值,然後通過聚合(DISTINCT)發送整個結果組。

由於功能遠遠沒有達到最佳的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導致一些內部的優化,這將使其執行速度稍快,情況因人而異。它有限制,但在這裏它會很好地工作。

編輯:刪除'外部'DISTINCT,因爲它(可能,參考我的第一個假設)不需要。