2005バージョン以降、MSSQLServerスクリプトのROW_NUMBER関数を利用することに慣れています。しかし、この関数を使用して大きなテーブルをクエリすると、パフォーマンスが大幅に低下することに気付きました。
4つの列を持つテーブルを想像してください(外部データベースの実際のテーブルにはより多くの列がありますが、例の複雑さを避けるためにそれらだけを使用しました):
DECLARE TABLE StockItems (
Id int PRIMARY KEY IDENTITY(1,1),
StockNumber nvarchar(max),
Name nvarchar(max),
[Description] nvarchar(max))
次のパラメータを使用して、200000以上の行で埋められたこのテーブルをクエリする手順を記述しました。
- @SortExpression-並べ替える列の名前
- @SortDirection-ビット情報(0 =昇順、1 =降順)
- @startRowIndex-行を取得するゼロベースのインデックス
- @maximumRows-取得する行数
クエリ:
SELECT sortedItems.Id
,si.StockNumber
,si.Name
,si.Description
FROM (SELECT s.Id
,CASE WHEN @SortDirection=1 THEN
CASE
WHEN CHARINDEX('Name',@SortExpression)=1 THEN
ROW_NUMBER() OVER (ORDER by s.Name DESC)
WHEN CHARINDEX('StockNumber',@SortExpression)=1 THEN
ROW_NUMBER() OVER (ORDER by s.StockNumber DESC)
ELSE ROW_NUMBER() OVER (ORDER by s.StockNumber DESC)
END
ELSE
CASE
WHEN CHARINDEX('Name',@SortExpression)=1 THEN
ROW_NUMBER() OVER (ORDER by s.Name ASC)
WHEN CHARINDEX('StockNumber',@SortExpression)=1 THEN
ROW_NUMBER() OVER (ORDER by s.StockNumber ASC)
ELSE ROW_NUMBER() OVER (ORDER by s.StockNumber ASC)
END
END AS RowNo
FROM stockItems s
) as sortedItems
INNER JOIN StockItems si ON sortedItems.Id=si.Id
ORDER BY sortedItems.RowNo
行数が急速に増加している状況では、すべての行をソートする必要があるため、ROW_NUMBERは無効になりました。
このパフォーマンスの不利を回避し、クエリを高速化するのを手伝ってもらえますか?