2012-10-30 8 views
11

私の前の質問からフォローアップ:APIクライアントに1,000,000件のデータベース結果を提供するにはどうすればよいですか?

Using "Cursors" for paging in PostgreSQL

1,000,000データベースの結果とAPIクライアントを提供するための良い方法は何ですか?

現在、PostgreSQLを使用しています。いくつかの提案方法:LIMITを使用して

  • ページング乱数を用いCursors
  • ページング(各クエリに「BY ORDERより大きい」追加)
  • を使用してページングとOFFSET(非常に大規模なデータセットのために破壊します)
  • 保存ファイルへの情報とクライアントがクライアントに
  • リターンキーのみを入力し、結果を介して
  • 反復をダウンロードしたクライアントサーバーにデータをPOSTさせ、その後のrequクライアントましょうAmazon S3のようなCloudファイルからのオブジェクトを推測します(まだファイル名を取得するためにページングが必要な場合があります)。

私はそれを考えていないのは、これらのオプションよりも単純で簡単です。

答えて

24

テーブルには主キーがあります。それを利用する。

LIMITOFFSETの代わりに、プライマリキーのフィルタを使用してページングを行います。乱数を用いて

ページング(各 クエリに「BY ORDERより大きい」を追加します)

をしかし、あなたはそれを行うべきかについてのランダムなものは何もありません:あなたはあなたのコメントでこれを示唆しました。

SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2 

クライアントがパラメータと、最後に見たIDと、フェッチするレコードの数の両方を指定できるようにします。あなたのAPIは、プレースホルダー、余分なパラメーター、または "最初にのIDを取得する"の代わりの呼び出しを必要とします。この場合、クエリからWHERE句が省略されますが、それは簡単です。

このアプローチでは、レコードを順番に取得するためにかなり効率的なインデックススキャンを使用します。通常、並べ替えやスキップされたすべてのレコードを繰り返し処理する必要はありません。クライアントは、一度にどれくらいの行を望むかを決めることができます。

このアプローチは、1つの重要な方法で同時実行の変更でLIMITOFFSETアプローチと異なります。キーがのテーブルにINSERTがある場合、のキーが既に見たキーよりも、このアプローチでは結果がまったく変わることはありませんが、OFFSETのアプローチが繰り返し行われます。同様に、DELETEのIDがすでに低いIDを持つ行の場合、このアプローチの結果は変更されませんが、OFFSETは見えない行をスキップします。ただし、生成されたキー付きの追加専用テーブルには違いはありません。

クライアントが結果セット全体を必要としていることが事前に分かっている場合は、最も効果的なのは、このページングビジネスを持たないすべての結果セットを送信することだけです。それで私はとなります。はカーソルを使用します。 DBから行を読み込んで、クライアントが受け付けるのと同じくらい速くそれらをクライアントに送ります。このAPIは、過度のバックエンド負荷を回避するためにクライアントがどれくらい遅いことが許されているかの制限を設定する必要があります。遅いクライアントの場合、私はおそらくページング(上記のように)に切り替えるか、カーソル全体の結果を一時ファイルにスプールして、DB接続を閉じます。

重要注意事項

1

APIには、開始するオフセットと、返すレコードの数を受け入れるようにしてください。これは、クライアントが1ページ要求で返すレコードの数を決定できるページングの一種です。また、APIはクエリの可能なレコードの総数を返す必要があります。したがって、クライアントは、返されたレコードの数が0個以下の場合に最後のレコードを取得したときに派生する「ページ」の数を知ることができます。レコードが要求されました。これは、SELECT文でOFFSET句(atの検索を開始するレコード)とLIMIT句(返すレコードの数)を使用してPostgresSQLクエリで制御できます。

+3

上使用に問題があることを見、制限する/オフセット

  • 異なる同時変更の動作信頼性が高いことがUNIQUE制約/ UNIQUEインデックスまたはPRIMARY KEYが必要ですOFFSETは、サーバーが "LIMIT"の前に結果セット全体を反復する必要があるため、非常に大きなデータセットでは分解されます。私は実際にこれを行ったAPIを使用しました。私たちは約10万回の結果後にデータを取得するのに大きな問題がありました。 –

  • 関連する問題