-1

Row_Number() を使用して、ストアド プロシージャにページングを実装しました。ページングは​​正常に機能しています。しかし問題は、Row_Number() を実装した後、インデックスが機能せず、主キー列をセクションごとに使用してもクラスター化インデックス SCAN が発生することです。以下はサンプルクエリです。

SELECT TOP (@insPageSize) A.RowNum, A.AdID, A.AdTitle, A.AdFor, A.AdCondition, 
A.AdExpPrice, A.CreatedDate, A.ModifiedDate, A.AdUID
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY vaa.AdID DESC) AS RowNum,
    vaa.AdID, vaa.AdTitle, vaa.CityID, vaa.AdFor, vaa.AdCondition, 
    vaa.AdExpPrice, vaa.CreatedDate, vaa.ModifiedDate, vaa.AdUID
FROM Catalogue.vwAvailableActiveAds vaa
WHERE vaa.CategoryID = @intCategoryID AND vaa.CountryCode = @chrCountryCode 
        AND vaa.CreatedDate > DATEADD(dd, -90, GETUTCDATE()) 
        AND vaa.StateID = @inbStateID AND vaa.CityID = @inbCityID
) A
WHERE A.RowNum > (@insPageSize * (@insPageNo - 1))

内部クエリのみを実行しようとすると:

 SELECT ROW_NUMBER() OVER (ORDER BY vaa.AdID DESC) AS RowNum,
    vaa.AdID, vaa.AdTitle, vaa.CityID, vaa.AdFor, vaa.AdCondition, 
    vaa.AdExpPrice, vaa.CreatedDate, vaa.ModifiedDate, vaa.AdUID
FROM Catalogue.vwAvailableActiveAds vaa
WHERE vaa.CategoryID = @intCategoryID AND vaa.CountryCode = @chrCountryCode 
        AND vaa.CreatedDate > DATEADD(dd, -90, GETUTCDATE()) 
        AND vaa.StateID = @inbStateID AND vaa.CityID = @inbCityID

インデックスは使用しません。AdID は主キーであり、すべての where 句をカバーする別の非クラスター化インデックスがあります。ただし、インデックス スキャンは発生します。内部クエリから Row_Number() を削除してその実行プランを確認すると、すべてのインデックスが正常に機能しますが、クラスター化されていないインデックスにある場合は、StateID と CityID が「述語」として表示されます。

両方の問題を解決するためのガイダンスを教えてください。

4

2 に答える 2

2

あなたは何を期待していますか?ここで、シークの実行を非常に困難にするいくつかのことを行っています。(a) 行の RANGE を返します。(b) AdID DESCで ROW_NUMBER() を取得するための並べ替え- おそらく PK が定義されている順序ではありません。(c) PK 以外のものに対してフィルタリングし、(d) NC インデックスでカバーされる可能性が低い多くの列を出力に含めます。多くの人が手を空中に投げて叫びます。実際、それが最も効率的な方法である場合でも。

(シークが発生しないからといって、「インデックスが機能しない」という意味ではありません。単に、このクエリを満たす効率がさらに低下する可能性があることを意味します。)

于 2013-02-23T16:28:59.263 に答える
0

row_number()最初にデータをフィルタリングする必要があるため、インデックスを使用していません。そして、これにはテーブル全体のスキャンが必要なようです。または、少なくとも、インデックスの複雑な組み合わせ。

インデックスを作成する場合はvwAvailableActiveAds(CategoryId, COuntryCode, StateId, CityId, CreatedDate)、このインデックスをwhere句に使用する必要があります。の適用row_number()は依然としてインデックスを使用しませんが、おそらくはるかに小さなデータ セットに対して行われます。

ところで、これは、ビューが実際には基礎となるテーブルの単なる選択であることを前提としています。ビュー内のクエリがより複雑な場合 (where句、join、またはであってもgroup by)、その特定のインデックスは最適な方法ではない可能性があります。

于 2013-02-23T16:23:25.203 に答える