2009-11-02 12 views
6

私はPostgreSQLの最適化をしていて、それには適切な仕事をしていないものを選んでいます。だから、私がPostgreSQLを不適切な仕事に使ってみようとしているときはいつでもそれを知りたいのですが、それはそれに適していて、すべてを正しく設定しなければなりません。多くのUPDATEとPostgreSQLを使用しているストリーム

とにかく、私は頻繁に変化する多くのデータを持つデータベースが必要です。

たとえば、多くのクライアントを持ち、2つの自己記述的に頻繁に更新されるプロパティbytes_receivedbytes_sentを持つISP(セッションを持つISP)を想像してください。各セッションはユニークなIDを持つ行で表され、彼らとの表は、あります:

CREATE TABLE sessions(
    id BIGSERIAL NOT NULL, 
    username CHARACTER VARYING(32) NOT NULL, 
    some_connection_data BYTEA NOT NULL, 
    bytes_received BIGINT NOT NULL, 
    bytes_sent BIGINT NOT NULL, 
    CONSTRAINT sessions_pkey PRIMARY KEY (id) 
) 

、会計データが流れるときに、この表には、これらのような更新の多く受ける:

-- There are *lots* of such queries! 
UPDATE sessions SET bytes_received = bytes_received + 53554, 
        bytes_sent = bytes_sent + 30676 
       WHERE id = 42 

おそらくMVCCのおかげで、(数千もの)セッションがたくさんあるテーブルのためのアップデートが非常にたくさん(1秒間に1〜2秒)更新されることなく、決して終わりのないストリームを受け取るので、PostgreSQL は非常にです。 Postgresはこの作業にはまったく適していません。私はこの仕事には適していないと思って、memcachedbのような別のストレージにそれらのカウンタを入れて、かなり静的なデータだけを使ってPostgresを使うのが良いでしょうか?しかし、私はこのデータを頻繁に照会する能力が欠けています。例えば、TOP10のダウンローダーを見つけることは、本当にうまくいきません。

残念ながら、データ量は、を大幅に下げることはできません。説明を簡単にするために、ISP会計の例がすべて考えられています。実際の問題は別のシステムであり、その構造は何とか説明するのが難しいです。

ありがとうございました!

答えて

12

データベースは実際には小さな更新プログラムをたくさん集めるのに最適なツールではありませんが、クエリ性とACIDの要件がわからないため、他に何か推奨することはできません。許容可能なアプローチであれば、zzzeekによって提案されたアプリケーション側の更新集約は、更新負荷を大幅に下げるのに役立ちます。

耐久性とある程度のパフォーマンスコストでより新しいデータをクエリする能力を提供する同様のアプローチがあります。更新が必要な値の変更を収集し、そこに変更を挿入できるバッファテーブルを作成します。トランザクション内で定期的にテーブルの名前を変更し、テーブルの代わりに新しいテーブルを作成します。その後、トランザクションですべての変更を集約し、対応するメインテーブルへの更新を行い、バッファテーブルを切り捨てます。このようにして、メインテーブルから選択してアクティブなバッファテーブルと名前を変更したバッファテーブルのすべての変更に参加できる、任意のデータの一貫性のある最新のスナップショットが必要な場合。

どちらも許容されない場合は、更新負荷が大きい場合にデータベースを調整することもできます。

アップデートを最適化するには、PostgreSQLでheap-only tuplesを使用して、更新された行のバージョンを保存できることを確認してください。これを行うには、頻繁に更新される列に索引がないことを確認し、fillfactorをデフォルトの100%より低いものに変更します。作業負荷と実行中のマシンの詳細に大きく依存するため、適切なフィルファクタを自分で把握する必要があります。 fillfactorは、autovacuumが古い非可視版をクリーンアップする機会を得る前に、すべての更新がすべて同じデータベースページに収まるように十分に低くする必要があります。自動密度設定をチューニングして、データベースの密度と真空間のオーバーヘッドをトレードオフすることができます。また、統計クエリを含む長いトランザクションは、トランザクションの開始後に変更されたタプルを保持することも考慮してください。 pg_stat_user_tablesにチューニングするために何を参照するにはビュー、n_dead_tupからn_tup_hot_updにn_tup_updn_live_tupの特に関係を参照してください。

重度の更新によっても、WAL(Write ahead Log)の負荷が高くなります。 WALの動作()を調整すると、それを下げるのに役立ちます。特に、より高いcheckpoint_segments数およびより高いcheckpoint_timeoutは、メモリ内でより多くの更新が行われるようにすることによって、IO負荷を大幅に低減することができます。いずれかの制限に達したために発生するチェックポイントの数を確認するには、pg_stat_bgwriterのcheckpoints_timedとcheckpoints_reqの関係を参照してください。あなたのshared_buffersを上げて、ワーキングセットがメモリに収まるようにすることも役に立ちます。 buffer_checkpointとbuffers_clean + buffers_backendを調べて、チェックポイント要件を満たすために書き込まれたメモリの数とメモリ不足だけを確認します。

6

統計更新は、ある種のメモリ内キューに発生するようにアセンブルする必要があります。より野心的な場合は、メッセージバスに挿入することもできます。受信プロセスでは、これらの統計的な更新を定期的に集計します。これは、5秒ごとから1時間ごとのいずれかになります。必要なものによって異なります。 bytes_receivedおよびbytes_sentのカウントが更新され、多数の個々の「更新」メッセージが合計された数を表す可能性があります。さらに、複数のIDの更新ステートメントを1つのトランザクションにバッチし、同じことを行っている他のトランザクションに対するデッドロックを防ぐために、更新ステートメントがプライマリキーに関して同じ相対順序で発行されるようにする必要があります。

このようにして、アクティビティをより大きなチャンクにまとめることで、PGデータベースの負荷量を制御したり、複数の同時アクティビティを単一のストリームにシリアル化したり(複数のスレッド/プロセスが更新を発行する)。 「期間」に基づいて調整するトレードオフは、新鮮度と更新負荷の量です。

関連する問題