2017-01-10 16 views
1

私は、ユーザーが過去7日間に発生したすべてのデータトラフィックを検索できるプログラムを用意しています。私はストアドプロシージャを使用してそのデータを取得します - 一度に250レコード(ユーザーはそれをページングすることができます)。問題は、ユーザーがそのデータを見たいと思ったときにタイムアウトが多く発生することでした。WHERE句を使用したFETCH OFFSETと同等のSQL Server 2008

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#の-methodから来たパラメータです。 このバージョンでは、私が望むデータを得るのに約1分35分必要でした。私は挿入COLをフィルタリングするWHERE句をinsered速くストアドプロシージャを作成するには(も私はこの列に索引を作った)とオフセット取り込みを使用する:

ストアドプロシージャを最適化後:

@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 

このバージョンでは約2秒でデータが得られます。唯一の問題は、私はMicrosoft SQL Server 2014で作業しますが、私のユーザーはSQL Server 2008+を使用しています。問題は今、Server 2008でOFFSET FETCHが動作しないことです。そして今、私はストアドプロシージャをどのように最適化して、SQl Server 2008で高速で動作するかはわかりません。

私は感謝しています任意のヘルプ:)

答えて

0

SQL Server 2005/2008でページネーションを処理するこのメソッドを試してください。

最初にROW_NUMBER()列の選択クエリにCTEを使用して、レコード番号/カウントを特定します。その後、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後のSelectスクリプトは同じままです。 –

+0

さて、私はそれを得ました、私はあなたの提案のような私のストアドプロシージャを変更しましたが、今私は私が欲しかったデータを取得するために約3分07分かかります(それは1分35分でした) – KatharinaG

関連する問題