テーブルには主キーがあります。それを利用する。
LIMIT
とOFFSET
の代わりに、プライマリキーのフィルタを使用してページングを行います。乱数を用いて
ページング(各 クエリに「BY ORDERより大きい」を追加します)
をしかし、あなたはそれを行うべきかについてのランダムなものは何もありません:あなたはあなたのコメントでこれを示唆しました。
SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2
クライアントがパラメータと、最後に見たIDと、フェッチするレコードの数の両方を指定できるようにします。あなたのAPIは、プレースホルダー、余分なパラメーター、または "最初にのIDを取得する"の代わりの呼び出しを必要とします。この場合、クエリからWHERE
句が省略されますが、それは簡単です。
このアプローチでは、レコードを順番に取得するためにかなり効率的なインデックススキャンを使用します。通常、並べ替えやスキップされたすべてのレコードを繰り返し処理する必要はありません。クライアントは、一度にどれくらいの行を望むかを決めることができます。
このアプローチは、1つの重要な方法で同時実行の変更でLIMIT
とOFFSET
アプローチと異なります。キーがのテーブルにINSERT
がある場合、のキーが既に見たキーよりも、このアプローチでは結果がまったく変わることはありませんが、OFFSET
のアプローチが繰り返し行われます。同様に、DELETE
のIDがすでに低いIDを持つ行の場合、このアプローチの結果は変更されませんが、OFFSET
は見えない行をスキップします。ただし、生成されたキー付きの追加専用テーブルには違いはありません。
クライアントが結果セット全体を必要としていることが事前に分かっている場合は、最も効果的なのは、このページングビジネスを持たないすべての結果セットを送信することだけです。それで私はとなります。はカーソルを使用します。 DBから行を読み込んで、クライアントが受け付けるのと同じくらい速くそれらをクライアントに送ります。このAPIは、過度のバックエンド負荷を回避するためにクライアントがどれくらい遅いことが許されているかの制限を設定する必要があります。遅いクライアントの場合、私はおそらくページング(上記のように)に切り替えるか、カーソル全体の結果を一時ファイルにスプールして、DB接続を閉じます。
重要注意事項:
上使用に問題があることを見、制限する/オフセット
UNIQUE
制約/UNIQUE
インデックスまたはPRIMARY KEY
が必要ですOFFSETは、サーバーが "LIMIT"の前に結果セット全体を反復する必要があるため、非常に大きなデータセットでは分解されます。私は実際にこれを行ったAPIを使用しました。私たちは約10万回の結果後にデータを取得するのに大きな問題がありました。 –