2016-07-15 134 views
0

我已經寫了下面的SQL存儲過程,並且因爲所有的選擇命令(我認爲)現在運行速度非常慢,數據庫已經填充了大量數據。有沒有一種方法來優化它,使其運行速度更快?目前在Azure S0 DB中,處理大約需要1分40秒。這裏的存儲過程:存儲過程優化

USE [cmb2SQL] 
GO 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 
CREATE PROCEDURE [dbo].[spStockReport] @StockReportId as INT 
AS 
    select 
     ProductId, 
     QtyCounted, 
     LastStockCount, 
     Purchases, 
     UnitRetailPrice, 
     CostPrice, 
     GrossProfit, 
     Consumed, 
     (Consumed * UnitRetailPrice) as ValueOfSales, 
     (QtyCounted * CostPrice) as StockOnHand, 
     StockCountId 
    from (
     select 
      ProductId, 
      QtyCounted, 
      LastStockCount, 
      Purchases, 
      UnitRetailPrice, 
      CostPrice, 
      GrossProfit, 
      (LastStockCount + Purchases) - QtyCounted as Consumed, 
      StockCountId 
     from (
      select 
       distinct 
       sci.StockCountItem_Product as ProductId, 
       (Select ISNULL(SUM(Qty), 0) as tmpQty from 
        (Select Qty from stockcountitems 
        join stockcounts on stockcountitems.stockcountitem_stockcount = stockcounts.id 
        where stockcountitem_Product = p.Id and stockcountitem_stockcount = sc.id and stockcounts.stockcount_pub = sc.StockCount_Pub 
        ) as data 
       ) as QtyCounted, 
       (Select ISNULL(SUM(Qty), 0) as LastStockCount from 
        (Select Qty from StockCountItems as sci 
         join StockCounts on sci.StockCountItem_StockCount = StockCounts.Id 
         join Products on sci.StockCountItem_Product = Products.id 
        where sci.StockCountItem_Product = p.id and sci.stockcountitem_stockcount = 
         (select top 1 stockcounts.id from stockcounts 
         join stockcountitems on stockcounts.id = stockcountitem_stockcount 
         where stockcountitems.stockcountitem_product = p.id and stockcounts.id < sc.id and StockCounts.StockCount_Pub = sc.StockCount_Pub 
         order by stockcounts.id desc) 
        ) as data 
       ) as LastStockCount, 
       (Select ISNULL(SUM(Qty * CaseSize), 0) as Purchased from 
        (select Qty, Products.CaseSize from StockPurchaseItems 
         join Products on stockpurchaseitems.stockpurchaseitem_product = products.id 
         join StockPurchases on stockpurchaseitem_stockpurchase = stockpurchases.id 
         join Periods on stockpurchases.stockpurchase_period = periods.id 
        where Products.id = p.Id and StockPurchases.StockPurchase_Period = sc.StockCount_Period and StockPurchases.StockPurchase_Pub = sc.StockCount_Pub) as data 
       ) as Purchases, 
       sci.RetailPrice as UnitRetailPrice, 
       sci.CostPrice, 
       (select top 1 GrossProfit from Pub_Products where Pub_Products.Pub_Product_Product = p.id and Pub_Products.Pub_Product_Pub = sc.StockCount_Pub) as GrossProfit, 
       sc.Id as StockCountId 
      from StockCountItems as sci 
       join StockCounts as sc on sci.StockCountItem_StockCount = sc.Id 
       join Pubs on sc.StockCount_Pub = pubs.Id 
       join Periods as pd on sc.StockCount_Period = pd.Id 
       join Products as p on sci.StockCountItem_Product = p.Id 
       join Pub_Products as pp on p.Id = pp.Pub_Product_Product 
      Where StockCountItem_StockCount = @StockReportId and pp.Pub_Product_Pub = sc.StockCount_Pub 
      Group By sci.CostPrice, sci.StockCountItem_Product, sci.Qty, sc.Id, p.Id, sc.StockCount_Period, pd.Id, sci.RetailPrice, pp.CountPrice, sc.StockCount_Pub 
     ) as data 
    ) as final 

GO 

如這裏要求在XML執行計劃(必須上傳到tinyupload,因爲它超過了消息字符長度):

execusionplan.xml

架構:

Table Schema

行數:

Table row_count 
StockPurchaseItems 57511 
Products 3116 
StockCountItems 60949 
StockPurchases 6494 
StockCounts 240 
Periods 30 
Pub_Products 5694 
Pubs 7 
+1

這麼多的子查詢,SP可能不.could你表現好,請在XML的形式發佈實際執行計劃,並與表一起參與表的模式計數 – TheGameiswar

+1

,而不是子查詢使用加入它會爲您提供了不錯的成績 –

+0

或創建臨時並將一個大查詢分解爲許多較小的查詢,然後將所有結果一起加入 – Tanner

回答

0

沒有進入查詢重寫,它是最昂貴的,你應該做的最後一件事可能。先逐一嘗試這些步驟,然後測量影響時間,執行計劃和SET STATISTICS IO ON輸出。首先爲這些指標創建基線。當你達到可接受的表現時停下來。

首先,更新有關表格的統計數據,我看到一些估計是有問題的。檢查執行計劃估計與實際行 - 現在更好嗎?

在StockPurchaseItems(StockPurchaseItem_Product)和StockCountItems(StockCountItem_Product,StockCountItem_StockCount)上創建索引。檢查執行計劃,優化器是否考慮使用索引?

向這兩個索引添加(包含)其他引用的列以涵蓋查詢。他們現在用了嗎?

如果上面沒有任何幫助,請考慮將查詢分解爲更小的查詢。有一些真實的數據可以用來做更具體的實驗。

**「選擇不同」氣味真的很糟糕,你確定連接都可以嗎?

+0

他在這部分代碼中至少運行了15k個查詢......它一團糟。 #Scarlarftw –