通常、このようにシステムを設計することはありません。通常、アプリケーションは単にカーソルを開き、500 行をフェッチし、それらの行をアプリケーションで処理し、次の 500 行をフェッチします。カーソルを閉じない限り、Oracle はシステムの時点で結果を返し続けます。カーソルを開いたときに番号 (SCN) を変更します。カーソルを開いた後に追加された行は返されず、カーソルを開いた後に削除された行は返されます。Oracle ではリーダーはライターをブロックしないため、このアプローチは他のアプリケーションがテーブルを使用することを妨げません (これは他のデータベースではしばしば問題になります)。
説明した方法でシステムを本当に設計したい場合は、一貫して順序付けできる列 (または列のセット) が必要です。これは、単調に増加する主キーのようなものでなければなりません (たとえば、シーケンス生成の主キー)。その後、次のようなことができます
SELECT *
FROM( SELECT a.*,
rownum rn
FROM( SELECT *
FROM table_name
ORDER BY some_key ) a
WHERE rownum <= MAX_ROW)
WHERE rn >= MIN_ROW
もちろん、この種のページネーション クエリでは、テーブルの「最後」に近づくにつれて、プロセスが遅くなります。最初の 500 行をソートするだけでよいため、最初の 500 行を取得するのはかなり効率的です。行 9,500 から 10,000 をフェッチする場合、20 倍のデータを並べ替えることになるため、クエリは桁違いに遅くなる可能性があります。テーブルが大きい場合、これにより通常、パフォーマンスが大幅に低下します。内部クエリで順序を反転するロジックを追加し、ページの半分をフェッチしたら「前の」ページのフェッチを開始することで、パフォーマンスを (わずかに) 向上させることができます。
このアプローチでは、行を見逃すこともあります。たとえば、ID
502 コミットを挿入するトランザクションが行 501 から 550 をフェッチすると、'ID' 501 を挿入するトランザクションがコミットすると、行 502 が表示されますが、行 501 は表示されません。