2012-10-11 183 views
1

你能幫我優化我的這個查詢嗎?我已經用盡了方法來優化這個。這裏的數據檢索時間是6分鐘,我想減少它。希望您能夠幫助我。需要幫助來優化此查詢

-- Main query 
DECLARE @ProdClass VARCHAR(10) 
,@ModelID VARCHAR(10) 
,@ServiceStartDate DATETIME 
,@ServiceEndDate DATETIME 
,@SvcID VARCHAR(10) 
,@StateID VARCHAR(10) 
,@AreaID VARCHAR(10) 

SET @ProdClass = 'WPS' 
SET @ModelID = 'BM' 
SET @ServiceStartDate = convert(datetime, '10/1/2007') 
SET @ServiceEndDate = CONVERT(DATETIME, '11/1/2007') 
SET @SvcID = '358' 
SET @StateID = 'JB' 
SET @AreaID = '' 

SELECT DISTINCT cus.MCUS_CUSID 
    ,cus.MCUS_ENAME 
    ,mod.MMOD_ENAME 
    ,rou.MROU_SERNO 
    ,svc.MSVC_SVCID AS SVC_NAME 
    ,ar.MARE_ENAME 
    ,dbo.ufn_GetLastXApptDate(rou.MROU_ROUID) AS MROU_APTDT 
    ,rou.MROU_LSVDT 
    ,(
     CASE MROU_FRSVE 
     WHEN 'Y' 
      THEN 'FREE' 
     WHEN 'N' 
      THEN 'NORMAL' 
     END 
    ) AS SERVICE_DUE_TYPE 
FROM dbo.MROU_FIL AS rou 
INNER JOIN dbo.MCUS_FIL AS cus ON rou.MROU_CUSID = cus.MCUS_CUSID 
INNER JOIN dbo.MMOD_FIL AS mod ON rou.MROU_MODID = mod.MMOD_MODID 
INNER JOIN dbo.MSVC_FIL AS svc ON rou.MROU_SVCID = svc.MSVC_SVCID 
INNER JOIN dbo.MADR_FIL AS adr ON cus.MCUS_CUSID = adr.MADR_CUSID 
INNER JOIN dbo.MSTA_FIL AS st ON adr.MADR_STAID = st.MSTA_STAID 
INNER JOIN dbo.MARE_FIL AS ar ON adr.MADR_AREID = ar.MARE_AREID 
INNER JOIN dbo.FAPT_FIL AS apt ON rou.MROU_ROUID = apt.FAPT_ROUID 
WHERE rou.MROU_STAT = 'ACTIVE' 
AND rou.MROU_CUSPF = 'MY' 
AND apt.FAPT_APTTY in ('mf','m1','m2','m3','m4','m5','m6', 'mm') 
AND ((@ProdClass = '') OR (@ProdClass <> '' AND rou.MROU_CLSID = @ProdClass)) 
AND ((@ModelID = '') OR (@ModelID <> '' AND rou.MROU_MODID = @ModelID)) 
AND (
    ((@ServiceStartDate = '') OR (@ServiceStartDate <> '' AND rou.MROU_LSVDT >= @ServiceStartDate)) 
    AND 
    ((@ServiceEndDate = '') OR (@ServiceEndDate <> '' AND rou.MROU_LSVDT <= @ServiceEndDate)) 
) 
AND ((@SvcID = '') OR (@SvcID <> '' AND svc.MSVC_SVCID = @SvcID)) 
AND ((@StateID = '') OR (@StateID <> '' AND adr.MADR_STAID = @StateID)) 
AND ((@AreaID = '') OR (@AreaID <> '' AND adr.MADR_AREID = @AreaID)) 
ORDER BY rou.MROU_LSVDT 


-- function -- 
ALTER FUNCTION [dbo].[ufn_GetLastXApptDate] 
(
@rouid numeric(18,0) 
) 
RETURNS datetime 
AS 
BEGIN 
    DECLARE @ApptDate datetime 

    SELECT @ApptDate = MAX(FAPT_APTDT) 
    FROM dbo.FAPT_FIL 
    WHERE FAPT_ROUID = @rouid 
     AND FAPT_STAT= 'X' 
     AND FAPT_APTTY in ('mf','m1','m2','m3','m4','m5','m6', 'mm') 

    RETURN @ApptDate 

END 
+1

你對錶有什麼指標?如果沒有,從那裏開始。 – CatchingMonkey

+0

實際上很多。我不知道從哪裏開始。 – Musikero31

+0

在你執行連接的每個鍵上至少應該有索引 - 除非表非常小。 – vstrien

回答

5

SQL Server必須調用每行的標量函數。爲了自由地將函數的查詢作爲基於集合的操作來執行,請將函數內聯移動。變化:

,dbo.ufn_GetLastXApptDate(rou.MROU_ROUID) AS MROU_APTDT 

到:

,(
SELECT MAX(FAPT_APTDT) 
FROM dbo.FAPT_FIL 
WHERE FAPT_ROUID = rou.MROU_ROUID 
     AND FAPT_STAT= 'X' 
     AND FAPT_APTTY in ('mf','m1','m2','m3','m4','m5','m6', 'mm') 
) 

您的查詢也像這可能從一個不同的版本不同的參數值執行計劃中受益的搜索查詢。在查詢結束

option (recompile) 

:您可以通過添加強制每次執行一個新的查詢計劃。

+0

如果您想要保留此函數中的代碼,請將其轉換爲返回:rouid,LastXApptDate的表函數。您不會得到與此答案相同的性能提升,但仍然可以重用該代碼。 – JeffO

+0

@JeffO:[內嵌表值函數](http://msdn.microsoft.com/en-us/library/ms189294(v = sql.105).aspx)與內聯代碼一樣高效。 – Andomar

+0

明白了。非常感謝!我不知道函數的調用總是會影響查詢的性能。 – Musikero31

0

嘗試用你的密鑰對所有列創建索引在要執行你的加入在他們出現在你的查詢每個表中的順序..