2017-01-10 58 views
1

我有一個程序,我的用戶可以用它查找過去7天發生的所有數據流量。我使用存儲過程來獲取數據 - 每次有250條記錄(用戶可以通過該頁面進行翻頁)。問題是,當用戶想看到這些數據時,用戶會得到很多超時。SQL Server 2008等同於帶有WHERE子句的FETCH OFFSET

這是我試圖優化ist之前的存儲過程。

@MaxRecCount INT, 
@PageOffset INT, 
@IncludeData BIT 

SELECT [Client], [Schema], [Version], [Records], [Fetched], [Receipted], [ProvidedAt], [FetchedAt], [ReceiptedAt],[PacketIds], [Record] FROM (
    SELECT TOP(@MaxRecCount) MAX(bai_ExportPendingArchive.[UserName]) AS Client, 
    MAX(bai_ExportPendingArchive.Category) AS [Schema], 
    MAX(bai_ExportPendingArchive.ContractVersion) AS [Version], 
    COUNT(*) AS [Records], 
    SUM (CASE WHEN bai_ExportPendingAckArchive.ExportPendingId IS NULL THEN 0 ELSE 1 END) as [Fetched], 
    SUM (CASE WHEN bai_ExportPendingAckArchive.Receipted IS NULL THEN 0 ELSE 1 END) as [Receipted], 
    MAX(bai_ExportArchive.Inserted) AS [ProvidedAt], 
    MAX(CASE WHEN bai_ExportPendingAckArchive.ExportPendingId IS NULL THEN NULL ELSE bai_ExportPendingAckArchive.Inserted END) AS [FetchedAt], 
    MAX(CASE WHEN bai_ExportPendingAckArchive.Receipted IS NULL THEN NULL ELSE bai_ExportPendingAckArchive.Receipted END) AS [ReceiptedAt], 
    bai_ExportArchive.PacketIds AS [PacketIds], 
    NULL AS [Record], 
    ROW_NUMBER() Over (Order By MAX(bai_ExportArchive.Inserted) desc) as [RowNumber] 
FROM bai_ExportArchive 
INNER JOIN bai_ExportPendingArchive ON bai_ExportArchive.Id = bai_ExportPendingArchive.ExportId 
LEFT OUTER JOIN bai_ExportPendingAckArchive ON bai_ExportPendingAckArchive.ExportPendingId = bai_ExportPendingArchive.Id 
GROUP BY bai_ExportPendingArchive.[UserName], bai_ExportArchive.PacketIds, bai_ExportPendingArchive.Category 
) AS InnerTable WHERE RowNumber > (@PageOffset * @MaxRecCount) and RowNumber <= (@PageOffset * @MaxRecCount + @MaxRecCount) 
ORDER BY RowNumber 

@MaxRecCount,@PageOffset和@IncludeData是那些從我的C# - 方法參數。 這個版本需要大約1:35分鐘才能獲得我想要的數據。爲了使存儲過程更快的I insered WHERE子句來篩選插入的山坳(也是我做了這列的索引),並使用OFFSET FETCH:

存儲過程的優化後:

@MaxRecCount INT, 
@PageOffset INT, 
@IncludeData BIT 

Declare @pageStart int 
Declare @pageEnd int 

SET @pageStart = @PageOffset * @MaxRecCount 
SET @pageEnd = @pageStart + @MaxRecCount + 50 

IF @IncludeData = 0 
    BEGIN 
     SELECT [Client], [Schema], [Version], [Records], [Fetched], [Receipted], [ProvidedAt], [FetchedAt], [ReceiptedAt],[PacketIds], [Record] FROM (
      SELECT TOP(@MaxRecCount) bai_ExportPendingArchive.[UserName] AS Client, 
      bai_ExportPendingArchive.Category AS [Schema], 
      MAX(bai_ExportPendingArchive.ContractVersion) AS [Version], 
      COUNT(*) AS [Records], 
      SUM (CASE WHEN bai_ExportPendingAckArchive.ExportPendingId IS NULL THEN 0 ELSE 1 END) as [Fetched], 
      SUM (CASE WHEN bai_ExportPendingAckArchive.Receipted IS NULL THEN 0 ELSE 1 END) as [Receipted], 
      MAX(bai_ExportArchive.Inserted) AS [ProvidedAt], 
      MAX(CASE WHEN bai_ExportPendingAckArchive.ExportPendingId IS NULL THEN NULL ELSE bai_ExportPendingAckArchive.Inserted END) AS [FetchedAt], 
      MAX(CASE WHEN bai_ExportPendingAckArchive.Receipted IS NULL THEN NULL ELSE bai_ExportPendingAckArchive.Receipted END) AS [ReceiptedAt], 
      bai_ExportArchive.PacketIds AS [PacketIds], 
      NULL AS [Record], 
      ROW_NUMBER() Over (Order By MAX(bai_ExportArchive.Inserted) desc) as [RowNumber] 
      FROM bai_ExportArchive 
      INNER JOIN bai_ExportPendingArchive ON bai_ExportArchive.Id = bai_ExportPendingArchive.ExportId 
      LEFT OUTER JOIN bai_ExportPendingAckArchive ON bai_ExportPendingAckArchive.ExportPendingId = bai_ExportPendingArchive.Id 
      Where bai_ExportArchive.Inserted <= (Select bai_ExportArchive.Inserted from bai_ExportArchive Order by bai_ExportArchive.Inserted DESC Offset @pageStart ROWS FETCH NEXT 1 ROWS Only) 
      And bai_ExportArchive.Inserted > (Select bai_ExportArchive.Inserted from bai_ExportArchive Order by bai_ExportArchive.Inserted DESC Offset @pageEnd ROWS FETCH NEXT 1 ROWS Only) 
      GROUP BY bai_ExportPendingArchive.[UserName], bai_ExportArchive.PacketIds, bai_ExportPendingArchive.Category 
      ) AS InnerTable 
     ORDER BY RowNumber 

這個版本給了我大約2s的數據。唯一的問題是,我在Microsoft SQL Server 2014上工作,但我的用戶使用SQL Server 2008+。現在的問題是,OFFSET FETCH dosn't在Server 2008中工作。現在我無能爲力,我可以優化我的存儲過程,它在SQl Server 2008上運行速度快。

我很感謝任何幫助:)

回答

0

試試這個方法來處理分頁SQL Server 2005/2008

首先使用CTE作爲您的選擇查詢,使用ROW_NUMBER()列標識記錄編號/計數。之後,您可以使用您的PAGE_NUMBERPAGE_COUNT從此CTE中選擇一系列記錄。示例如下

DECLARE @P_PAGE_NUM  INT = 0 
     ,@P_PAGE_SIZE INT = 20 

    ;WITH CTE 
    AS 
    ( /*SELECT ROW_NUMBER() OVER (ORDER BY COL_to_SORT DESC) AS [ROW_NO] 
       ,... 
     WHERE .... 
     */ -- You can replace your select query here, but column [ROW_NO] should be there in your select list. 
      --ie ROW_NUMBER() OVER (ORDER BY put_column-to-sort-here DESC) AS [ROW_NO] 
    ) 

    SELECT * 
      --,( SELECT COUNT(*) FROM CTE) AS [TOTAL_ROW_COUNT] 
    FROM CTE 
    WHERE ( 
       ISNULL(@P_PAGE_NUM,0) = 0 OR 
       [ROW_NO] BETWEEN ( @P_PAGE_NUM - 1) * @P_PAGE_SIZE + 1 
           AND  @P_PAGE_NUM  * @P_PAGE_SIZE 
      ) 
    ORDER BY [ROW_NO] 
+0

謝謝你的回答。說實話:我不知道如何將你的建議插入我的存儲過程。 – KatharinaG

+0

您可以在CTE中替換您的選擇查詢,但'ROW_NUMBER()OVER(ORDER BY [put_column-to-sort-here] DESC)AS [ROW_NO]'列應該在那裏對記錄進行排序,那麼只有我們可以維護記錄中的訂單序列。 CTE之後的選擇腳本將保持不變。 –

+0

好吧,現在我知道了,我改變了我的存儲過程,就像你建議的那樣,但是現在需要大約3分07分鐘才能得到我想要的數據(比如1:35分鐘) – KatharinaG