私は、ユーザーが過去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で高速で動作するかはわかりません。
私は感謝しています任意のヘルプ:)
ありがとうございます。正直言って:私はどのように私のストアドプロシージャにあなたの提案を挿入するか分からない。 – KatharinaG
CTE内で選択したクエリを置き換えることはできますが、レコードをソートするには 'ROW_NUMBER()OVER(ORDER BY [put_column-to-sort-here] DESC)AS [ROW_NO]'カラムが必要です。レコード内の順序シーケンスそして、CTE後のSelectスクリプトは同じままです。 –
さて、私はそれを得ました、私はあなたの提案のような私のストアドプロシージャを変更しましたが、今私は私が欲しかったデータを取得するために約3分07分かかります(それは1分35分でした) – KatharinaG