他の人がすでに指摘したように、クエリは異なる結果を返し、リンゴとオレンジを比較しています。
しかし、根本的な疑問は残ります。どちらが速いか:キーセット駆動型ページングまたは行番号駆動型ページング?
キーセットページング
キーセット駆動型ページングは、最後に表示されたページの上部と下部のキーを記憶し、上部/最後のキーセットに基づいて次または前の行のセットを要求することに依存しています。
次のページ:
select top (<pagesize>) ...
from <table>
where key > @last_key_on_current_page
order by key;
前のページ:
select top (<pagesize>)
from <table>
where key < @first_key_on_current_page
order by key desc;
このアプローチには、ROW_NUMBERアプローチ、またはMySQLの同等のLIMITアプローチに比べて2つの主な利点があります。
- 正しい :行番号ベースのアプローチとは異なり、新しいエントリと削除されたエントリを正しく処理します。その間にページ2の行23が削除されたという理由だけで、ページ4の最後の行がページ5の最初の行として表示されません。また、ページ間で行が不思議に消えることもありません。これらの異常はrow_numberベースのアプローチで一般的ですが、キーセットベースのソリューションはそれらを回避する上ではるかに優れた仕事をします。
- 速い :すべての操作は、高速の行ポジショニングとそれに続く目的の方向への範囲スキャンで解決できます
ただし、このアプローチは難しい 実装するため、平均的なプログラマーには理解しにくく、ツールではサポートされていません。
駆動される行数
これは、Linqクエリで導入される一般的なアプローチです:
select ...
from (
select ..., row_number() over (...) as rn
from table)
where rn between @firstRow and @lastRow;
(またはTOPを使用した同様のクエリ)このアプローチは簡単 実装し、ツール(特に、Linq .Limitおよび.Take演算子)によってサポートされます。ただし、このアプローチは保証されています 行をカウントするためにインデックスをスキャンします。このアプローチは通常、ページ1で非常に高速に機能し、ページ番号が大きくなるにつれて徐々に遅くなります。
ボーナスとして、このソリューションを使用すると、並べ替え順序を非常に簡単に変更できます(OVER句を変更するだけです)。
全体として、ROW_NUMBER()ベースのソリューションの使いやすさ、Linqからのサポート、中程度のデータセットに任意の順序を使用する簡単さを考えると ROW_NUMBERベースのソリューションで十分です。大規模および非常に大規模なデータセットの場合、ROW_NUMBER()は重大なパフォーマンスの問題を引き起こす可能性があります。
考慮すべきもう1つのことは、多くの場合、アクセスの明確なパターンがあるということです。多くの場合、最初の数ページはホットで、10ページ以降のページは基本的に表示されません(たとえば、最新の投稿)。この場合、下部のページ(開始結果の行を取得するために多数の行をカウントする必要がある表示ページ)にアクセスした場合にROW_NUMBER()で発生するペナルティは無視できます。
そして最後に、キーセットのページ付けは、ROW_NUMBER()では簡単に対応できない辞書ナビゲーションに最適です。辞書ナビゲーションでは、ページ番号を使用する代わりに、ユーザーはアルファベットなどの特定のアンカーに移動できます。典型的な例は、サイドバーのような連絡先Rolodexで、Mをクリックして、Mで始まる最初の顧客名に移動します。