2012-10-17 19 views
8

私は10m行の大きなテーブルを持っています。そして、私は各列の統計値を取得する必要があります。私はこの値を生成する関数を持っています、例えばGetStatistic(uuid)です。この機能はありませんしばしば非常に遅く、結果値の変化を動作しますので、私は私のテーブルの列Statisticを作成した、と一日一回、このようなクエリを実行します。GetStatisticを呼び出すことなくPostgreSQL。パラレルで更新クエリを実行できますか?

UPDATE MyTable SET Statistic = GetStatistic(ID); 

と私は列Statisticを使用するselectクエリ内を機能。

問題は、私の本番サーバーには64のCPUとたくさんのメモリがあるため、ほぼすべてのDBをRAMにキャッシュすることができますが、このクエリはCPUを1つしか使用せず、2〜3時間の実行が必要です。

GetStatistic関数の使用テーブルで、UPDATEクエリのすべての実行中に定数です。使用可能なすべてのCPUを使用して、異なる行のパラレルで同時にGetStatisticを計算するためにpostgreを取得するクエリを変更できますか?

+0

なぜ関数を使用するのですか、プレーンSQLでは実現できないものはありますか?関数は現在の行からの値のみを必要とするのか、それとも他のデータソース(:=テーブル)も含むのですか?ところで、私たちにその機能を教えてください。 – wildplasser

+0

このクエリの計画をチェックすると、この関数が10M回呼ばれることがわかります。たぶん純粋なSQLで記述するほうがいいでしょうし、はるかに高速かもしれません。 –

答えて

9

PostgreSQLは単一のバックエンドで各クエリを実行します。これは単一のスレッドを持つプロセスです。クエリに複数のCPUを使用することはできません。また、単一のクエリ内で達成できるI/O並行性には多少の制限があり、実際にはビットマップ索引スキャンのための並行I/Oのみを行い、それ以外の場合はOSとディスクシステムを使用して同時I/Oを行います。

Pgは、多数の小さなクエリが同時にロードされている場合に適しており、システムをそのように飽和させるのは簡単です.1つまたは2つの非常に大きなクエリに対してシステムリソースを最大限に活用することができません。

あなたができることは、仕事を分割して労働者に渡すことです。あなたがこれに言及しました:

私はすべてのavaliableのCPUを使用して、同時に異なる行に対してparalel でGetStatisticを計算するpostgreを取得するためにクエリを変更することはできますか?

仕事のこの種のを支援するために設計されていDBlinkPL/ProxypgbouncerPgPool-IIのようなツールの様々なものがあります。あるいは、データベースに接続する8人のワーカーを起動して、重複しないID範囲を持つ文をUPDATE ... WHERE id BETWEEN ? AND ?実行して、自分で行うこともできます。より洗練されたオプションは、キューコントローラが約1000個のIDの範囲を従業員に渡すようにすることです。範囲はUPDATEで、新しい範囲を要求します。

64 CPUは、64人の並行作業者が理想的であるとは限りません。あなたのディスクI/Oは、書き込みにはあまりにも重要な要素です。 UPDATEトランザクションにcommit_delayを使用し、(このデータのビジネス要件が安全である場合)synchronous_commit = 'off'を使用するように設定すると、同期からの負荷を大幅に削減する必要があります。それにもかかわらず、最高のスループットは、64人の並行作業者よりも十分に低いと考えられます。

GetStatistic関数は、ループ重い手続き型PL/pgSQL関数ではなく、インライン化可能なSQL関数またはビューに変換することによって、より高速に行うことができます。あなたがこの機能を示してくれれば助けになるかもしれません。

関連する問題