2010-08-16 111 views
1

全部,sql查詢需要更多時間在視圖中運行

我有一個巨大的SQL查詢。當我把這個查詢存儲Proc它需要5秒鐘來執行我運行它只是作爲一個查詢它需要4-5秒,但當我在視圖中運行它需要5分鐘。

請告知爲什麼它的運行速度慢的觀點

SQL查詢如下:基於您的評論

CREATE VIEW dbo.Client_Billing_RS  
AS   
SELECT DISTINCT TOP (100) PERCENT  
CLIENT.OH_Code AS CLIENT,  
BUYER.OH_Code AS BUYER,  
dbo.Client_ReturnWK(pallet.MB_PR_CLOSED_DT) AS WEEKNUM,  
dbo.Client_PadString(DATEPART(MONTH, CONVERT(varchar(8), pallet.MB_PR_CLOSED_DT, 112)), '0', 2) AS MONTH,  
DATEPART(YEAR, CONVERT(varchar(8), pallet.MB_PR_CLOSED_DT, 112)) AS YEAR,  
shipment.JS_ActualVolume,  
shipment.JS_ActualWeight,  
packing.MB_PD_Units ,  
orderHeader.JD_OH_Buyer,  
OrgMiscServ_1.OM_CustomAttrib3,   
shipment.JS_TransportMode AS MODE,  
shipment.JS_UniqueConsignRef ,  
consol.JK_UniqueConsignRef,   
DestRefCountry.RN_Desc,  
part.OP_PartNum,  
part.OP_Desc AS TITLE,  
CONVERT(VARCHAR(8), part.OP_CustomAttrib1, 1) AS COVER_DATE,  
docketLine.WE_CustomDate1 AS ON_SALE_DATE,  
docketLine.WE_CustomAttrib3 AS US_BARCODE,  
part.OP_CustomAttrib3 AS UK_BARCODE,  
CASE WHEN freight IS NULL THEN 0 ELSE freight END AS FREIGHT,  
CASE WHEN war IS NULL THEN 0 ELSE war END AS WAR,  
CASE WHEN fuel IS NULL THEN 0 ELSE FUEL END AS FUEL,  
shipment.JS_ActualChargeable * 1000 AS CHRG_KG,  
shipment.JS_PackingMode,  
'' AS MIN_CHRG,  
BUYER.OH_FullName AS BUYER_NAME,   
CASE WHEN Client_MF_Billing_Job_Cost_PIVOT.FUEL + Client_MF_Billing_Job_Cost_PIVOT.WAR IS NULL   
         THEN 0 ELSE Client_MF_Billing_Job_Cost_PIVOT.FUEL + Client_MF_Billing_Job_Cost_PIVOT.WAR END AS SUR_AMT1,   
(packing.MB_PD_Units * part.OP_Weight) * (CASE WHEN rate IS NULL THEN 0 ELSE RATE END + (CASE WHEN JS_TransportMode = 'AIR' THEN CASE WHEN FUEL_LOOKUP IS NULL   
         THEN 0 ELSE FUEL_LOOKUP END ELSE 0 END)) AS TITLE_AMT,  
consol.JK_CustomDate1 AS LOAD_DATE_OLD,  
docket.WD_DocketID,  
orderHeader.JD_IsCancelled,  
CASE WHEN RATE IS NULL THEN 0 ELSE rate END AS RATE,  
packing.MB_PD_Units * part.OP_Weight * CASE WHEN Client_Tariff_Job_Rate.RATE IS NULL THEN 0 ELSE rate END AS FRT_AMT,  
part.OP_PK,  
CASE WHEN LEN(part.OP_CustomAttrib2)= 1 THEN '0' + OP_CustomAttrib2 ELSE OP_CustomAttrib2 END AS ISSUE_NUMBERx,  
'9' + LEFT(dbo.Client_PadString(part.OP_CustomAttrib2, '0', 2), 2) AS ISSUE_NUMBER,  
Client_Consol.ETD AS LOAD_DATE,   
CASE WHEN docketLine.WE_CustomAttrib3 IS NULL THEN '' ELSE SUBSTRING(docketLine.WE_CustomAttrib3, 7, 5) END AS UPC_CODE,  
BUYER.OH_PK AS BUYER_PK,  
CLIENT.OH_PK AS CLIENT_PK,  
CASE WHEN LEN(SUBSTRING(part.OP_PartNum,1, CASE WHEN CHARINDEX('-', part.OP_PartNum) > 0 THEN CHARINDEX('-', part.OP_PartNum) - 1 ELSE 0 END))   
    = 0 THEN OU_LocalPartNumber ELSE SUBSTRING(part.OP_PartNum, 1, CASE WHEN CHARINDEX('-',   
         part.OP_PartNum) > 0 THEN CHARINDEX('-', part.OP_PartNum) - 1 ELSE 0 END) END AS MAG_CODE,  

CASE WHEN JS_TransportMode = 'AIR' THEN (FUEL_LOOKUP) * (ROUND(packing.MB_PD_Units * part.OP_Weight + .5, 0)) ELSE 0 END AS SUR_AMT,  
CASE WHEN JS_TransportMode = 'AIR' THEN FUEL_LOOKUP ELSE 0 END AS FUEL1,   
Client_Tariff_Job_Rate.WAR_LOOKUP AS SUGGESTED_WAR,  
Client_Tariff_Job_Rate.FUEL_LOOKUP AS SUGGESTED_FUEL,   
Client_Tariff_Job_Rate.SHIPPING_LINE,  
OrgMiscServ.OM_CustomAttrib1,  
OrgMiscServ.OM_CustomDate1,  
CLIENT.OH_PK AS ClientPK,  
part.OP_Weight,  
packing.MB_PD_Units * part.OP_Weight AS FRT_WEIGHT,  

packing.MB_PD_Units * part.OP_Weight + Client_CHRG_PALLET.PALLET_KG_PORTION AS FRT_WEIGHT_GROSS,   
(packing.MB_PD_Units * part.OP_Weight + Client_CHRG_PALLET.PALLET_KG_PORTION)   
         * CASE WHEN Client_Tariff_Job_Rate.RATE IS NULL THEN 0 ELSE rate END AS FRT_AMT_GROSS,  

(packing.MB_PD_Units * part.OP_Weight + Client_CHRG_PALLET.PALLET_KG_PORTION) * (CASE WHEN rate IS NULL   
         THEN 0 ELSE RATE END + (CASE WHEN JS_TransportMode = 'AIR' THEN CASE WHEN FUEL_LOOKUP IS NULL   
         THEN 0 ELSE FUEL_LOOKUP END ELSE 0 END)) AS TITLE_AMT_GROSS,  
orderHeader.JD_PK,  
orderHeader.JD_OrderNumber,   
Client_Tariff_Job_Rate.ONWARD_DELIVERY,   
packing.MB_PD_Units * part.OP_Weight * CASE WHEN Client_Tariff_Job_Rate.ONWARD_DELIVERY IS NULL   
         THEN 0 ELSE ONWARD_DELIVERY END AS ONWARD_DELIVERY_AMT,  
docketLine.WE_CustomDecimal4 AS COVER_PRICE,  
CLIENT.OH_FullName,  
(packing.MB_PD_Units * (part.OP_Weight + 0.009) + Client_CHRG_PALLET.PALLET_KG_PORTION)   
         * CASE WHEN Client_Tariff_Job_Rate.RATE IS NULL THEN 0 ELSE rate END AS FRT_AMT_GROSS_UPLIFT,   
(packing.MB_PD_Units * (part.OP_Weight + 0.009) + Client_CHRG_PALLET.PALLET_KG_PORTION)  
         * (CASE WHEN rate IS NULL THEN 0 ELSE RATE END + (CASE WHEN JS_TransportMode = 'AIR' THEN CASE WHEN FUEL_LOOKUP IS NULL   
         THEN 0 ELSE FUEL_LOOKUP END ELSE 0 END)) AS TITLE_AMT_GROSS_UPLIFT,   
packing.MB_PD_Units * (part.OP_Weight + 0.009) AS FRT_WEIGHT_UPLIFT,   
packing.MB_PD_Units * (part.OP_Weight + 0.009) + Client_CHRG_PALLET.PALLET_KG_PORTION AS FRT_WEIGHT_GROSS_UPLIFT,  
part.OP_Weight + 0.009 AS COPY_KG_UPLIFT,  
(packing.MB_PD_Units * (part.OP_Weight + 0.009)) * (CASE WHEN rate IS NULL   
         THEN 0 ELSE RATE END + (CASE WHEN JS_TransportMode = 'AIR' THEN CASE WHEN FUEL_LOOKUP IS NULL   
         THEN 0 ELSE FUEL_LOOKUP END ELSE 0 END)) AS TITLE_AMT_UPLIFT,  
packing.MB_PD_Units * (part.OP_Weight + 0.009) * CASE WHEN Client_Tariff_Job_Rate.RATE IS NULL THEN 0 ELSE rate END AS FRT_AMT_UPLIFT,   
packing.MB_PD_Units * (part.OP_Weight + 0.009) * CASE WHEN Client_Tariff_Job_Rate.ONWARD_DELIVERY IS NULL THEN 0 ELSE ONWARD_DELIVERY END AS ONWARD_DELIVERY_AMT_UPLIFT,  
packing.MB_PR_PalletRef  

FROM Client_whspalletpacking packing WITH (NOLOCK)  
inner join whsDocketLine docketLine WITH (NOLOCK) on packing.we_fk =docketline.we_pk  
inner join whsDocket docket WITH (NOLOCK) on docketline.we_wd =docket.wd_pk  
inner join client_whspallet pallet WITH (NOLOCK) on packing.MB_PD_PR = pallet.MB_PR_PK  
inner join jobshipment shipment WITH (NOLOCK) on packing.mb_js= shipment.js_pk  
inner join jobOrderHeader orderHeader WITH (NOLOCK) on docket.WD_ExternalReference =OrderHeader.JD_OrderNumber  
inner join orgheader Client WITH (NOLOCK) on docket.wd_oh_client= Client.oh_pk  
inner join orgheader Buyer WITH (NOLOCK) on packing.MB_PR_OH=Buyer.oh_pk  
inner join jobconsol consol WITH (NOLOCK) on packing.mb_jk=consol.jk_pk  
INNER JOIN OrgSupplierPart part WITH (NOLOCK) ON docketline.WE_OP = part.OP_PK  
inner join OrgPartRelation WITH (NOLOCK) on part.op_pk=OrgPartRelation.OU_OP  
LEFT JOIN RefUNLOCO As DestUNLOCO WITH (NOLOCK) On DestUNLOCO.RL_Code = shipment.JS_RL_NKDestination  
LEFT JOIN RefCountry As DestRefCountry WITH (NOLOCK) On DestRefCountry.RN_PK = DestUNLOCO.RL_RN  
LEFT OUTER JOIN Client_Tariff_Job_Rate WITH (NOLOCK) ON orderHeader.JD_PK = Client_Tariff_Job_Rate.JOB_ORDER_PK  
LEFT OUTER JOIN Client_MF_Billing_Job_Cost_PIVOT WITH (NOLOCK) ON packing.MB_JH = Client_MF_Billing_Job_Cost_PIVOT.JR_JH  

inner join Client_CHRG_PALLET WITH (NOLOCK) on packing.WE_FK = Client_CHRG_PALLET.WE_FK and packing.mb_pr_palletref=Client_CHRG_PALLET.mb_pr_palletref ---change  
left outer join OrgMiscServ WITH (NOLOCK) on CLIENT.OH_PK =OrgMiscServ.OM_OH  
inner join OrgMiscServ AS OrgMiscServ_1 WITH (NOLOCK) on BUYER.OH_PK =OrgMiscServ_1.OM_OH  
left outer join Client_Consol WITH (NOLOCK) on consol.jk_pk=Client_Consol.CONSOL_PK  
where (DestRefCountry.RN_Desc = 'United States')   
ORDER BY CLIENT, TITLE, BUYER, MONTH DESC, WEEKNUM DESC, MODE DESC 
+1

你能否向我們展示有問題的代碼? – 2010-08-16 12:11:06

+1

它不應該做,除非有更多。你能提供代碼嗎? – 2010-08-16 12:12:36

+0

你有一個過濾器的視圖(不是裏面呢=? – gbn 2010-08-16 12:21:16

回答

1

我同意Vash的觀點,即作爲vaiew運行的額外時間可能是由於額外的時間來編譯執行計劃。

嘗試運行此

Set Statistics Time On 
Select * from view 

and then Set Statistics On 
Exec yourSPHere 

你會得到這樣的事情

SQL Server分析和編譯時間:
CPU時間= 0毫秒,經過的時間= 1毫秒。

SQL Server執行時間:CPU 時間= 0毫秒,已用時間= 1毫秒。

(5475行受影響)表 'ContactBase'。掃描計數1,邏輯讀取 428,物理讀取0, 預讀0,lob邏輯讀取 0,lob物理讀取0次,lob 預讀0

SQL Server的執行時間:CPU 時間= 47ms,經過時間= 470ms。

如果「SQL Server解析和編譯時間:」解釋了您的答案是視圖必須每次創建執行計劃時使用緩存執行計劃的兩次之間的差異。

+0

編譯時間最長的是什麼?抱歉,最後的編輯沒有任何意義。視圖不能被參數化。 – 2010-08-16 13:16:43

+0

@馬丁史密斯:約3-4分鐘,但結構較簡單。 – 2010-08-16 13:24:03

+0

@Vash - 好的 - 我從來沒有經歷過類似的事情。但我不認爲我曾經在OP的帖子中做過20次表連接!猜猜我們必須等待OP報告。 – 2010-08-16 13:35:48

3

,我懷疑你打了「predicate pushing」的問題(搜索這句話)

觀察...左邊的WHERE JOIN變化這一個JOIN

LEFT JOIN RefCountry As DestRefCountry... 
.... 
where (DestRefCountry.RN_Desc = 'United States') 
+1

我不知道這個現象有一個名字,但我同意 - 它看起來像過濾可能被推遲,如果我們可以看到計劃,我們肯定知道。 – Matt 2010-08-16 13:40:08

1

提示:與

ISNULL(freight, 0); 

更換

CASE WHEN freight IS NULL THEN 0 ELSE freight END AS FREIGHT, 

當您使用存儲過程的執行計劃是編譯和存儲,以便SQL引擎不必創建它。

當您將此作爲查詢運行時您可能已將此計劃存儲在緩存中,這就是爲什麼在執行過程中沒有差異。

可能當您使用視圖時,執行計劃必須從頭開始創建。

+0

感謝您的回覆,但它是否每次都從頭創建執行計劃? – Amit 2010-08-16 12:40:00

+0

@ Martin--當在視圖中運行查詢並執行「S​​ELECT * FROM sys.dm_tran_locks where resource_database_id = '28'」並排時,我在結果中看到很多記錄 – Amit 2010-08-16 13:07:40

+0

@Amit - 通常不會。該定義的長度是'8081'字符。我似乎記得很長的定義可能會因計劃緩存而得到不同的處理,但不能記住我頭頂的任何細節。我懷疑這可以解釋5分鐘的差異。 – 2010-08-16 13:09:54