0

プロジェクトでは、バイナリ データを PostgreSQL (プロジェクト要件) データベースに格納する必要があります。その目的のために、次の列を持つテーブルを作成しました。

id   : integer, primary key, generated by client
data : bytea, for storing client binary data

クライアントは、Linux 上で実行される C++ プログラムです。行を挿入 (バイナリ データのチャンクで初期化) し、その後更新 (追加のバイナリ データをデータ フィールドに連結) する必要があります。簡単なテストでは、これによりパフォーマンスが向上することが示されています。

入力に応じて、クライアントが並行スレッドを使用してデータを挿入/更新するようにします (異なる DB 接続を使用)、または 1 つの DB 接続のみを使用する単一スレッドを使用します。

私たちは PostgreSQL の経験があまりないので、ボトルネックの可能性と、複数のスレッドを使用してデータを挿入する方が単一のスレッドを使用するよりも優れているかどうかについて、いくつかの指針を教えていただけませんか。

ありがとうございました :)

編集1:

詳細情報:

  • 1 つの Linux プロセスのみを使用してデータベースにアクセスするクライアントは 1 つだけです。
  • データベースとクライアントは同じ高性能サーバー上にありますが、これは問題ではありません。クライアントはマシンに関係なく高速である必要があり、追加のクライアント構成は必要ありません。
  • 10 秒ごとに新しいデータ ストリームを取得し、ストリームは 0.5 秒ごとに新しい 16000 バイトを提供します (CBR、ただしバッファリングを使用でき、最大 4 秒ごとに挿入のみを実行できます)。
  • ストリームは 10 秒から 5 分間続きます
4

1 に答える 1

2

を使用している場合、行を挿入してから追加する方がパフォーマンスが向上するということは、ほとんど意味がありませんbytea

PostgreSQL の MVCC 設計は、 anが aおよび anUPDATEと論理的に同等であることを意味します。行を挿入してから更新すると、挿入した元のタプルが削除済みとしてマークされ、古いデータと追加されたデータの連結を含む新しいタプルが書き込まれます。DELETEINSERT

あなたのテスト方法について質問します。挿入してから追加する方が速いと判断した理由を詳しく説明していただけますか? 意味がない。

それを超えて、この質問は広すぎて、実際に多くのことを言うには書かれていないと思います。詳細や数値は提供していません。バイナリ データ サイズの見積もり、行数の見積もり、クライアント数の見積もりなどはありません。

bytea挿入パフォーマンスは、PostgreSQL の他の挿入パフォーマンス チューニングと変わりません。同じアドバイスがすべて当てはまります: バッチ作業をトランザクションに分割し、複数の同時セッションを使用して (ただし、多すぎない; 経験則は number_of_cpus + number_of_hard_drives です) データを挿入し、トランザクションが互いのデータを使用しないようにしてUPDATE、ロックを必要としないようにします。バッテリでバックアップされた RAID コントローラなどのような安全なライトバック キャッシュを備えたディスク サブシステムがない場合は、async commit および/または commit_delay を使用します。

メインのコメント スレッドで提供された最新の統計情報を考えると、消費したいデータの量は、適切なハードウェアとアプリケーションの設計で完全に実用的なように思えます。入ってくるすべてのブロックをコミットしなければならない場合、1 秒あたり約 60 のトランザクションが必要になるため、通常のハード ドライブでもピーク負荷を達成できる可能性があります。を使用しcommit_delayて、グループ コミットを達成し、fsync() のオーバーヘッドを大幅に削減したりsynchronous_commit = off、クラッシュの場合にトランザクションのタイム ウィンドウを失う余裕がある場合に使用することもできます。

バッテリ バックアップ式のキャッシュ RAID コントローラや信頼性の高い電力損失セーフ キャッシュを備えた SSD などのライトバック キャッシュ ストレージ デバイスを使用すると、この負荷に簡単に対処できます。

これについてさまざまなシナリオのベンチマークを行っていないため、一般的な用語しか話せません。これを自分で設計する場合、PostgreSQL でのチェックポイント ストールが心配になり、少しのデータをバッファリングできることを確認したいと思います。できるようですので、大丈夫なはずです。

私の見解では、おそらく最も実用的であるため、テスト、ベンチマーク、および負荷テストを行う最初のアプローチを次に示します。

データ ストリームごとに 1 つの接続synchronous_commit = off+ a commit_delay.

INSERT16kb の各レコードがステージング テーブルに入ると (可能であればUNLOGGED、またはTEMPORARY不完全なレコードを失う余裕がある場合)、Pg にコミットを同期させてグループ化させます。各ストリームが終了したら、バイト配列を読み取り、それらを連結して、レコードを最終テーブルに書き込みます。

このアプローチで最高の速度を得るには、bytea_agg集計関数をbytea拡張モジュールとして実装します (そして、将来のバージョンに含めるために PostgreSQL に送信します)。実際には、データを読み取るか、非効率的で非線形のスケーリングを使用して、アプリケーションで bytea 連結を実行することで回避できる可能性があります。

CREATE AGGREGATE bytea_agg(bytea) (SFUNC=byteacat,STYPE=bytea);

INSERT INTO final_table SELECT stream_id, bytea_agg(data_block) FROM temp_stream_table;

チェックポインティングの動作を確実に調整する必要があります。これらの 16kb レコードを蓄積するためにUNLOGGEDテーブルではなく通常のテーブルまたはテーブルを使用しているTEMPORARY場合は、それがかなり積極的にVACUUM編集されていることを確認する必要があります。

以下も参照してください。

于 2013-01-26T05:47:48.360 に答える