web-dev-qa-db-ja.com

PostgreSQLで高いINSERTパフォーマンスを維持するには

私は、測定ファイルのデータをPosgres 9.3.5データベースに解析するプロジェクトに取り組んでいます。

中心にあるのは、各測定ポイントの行を含むテーブル(月ごとに分割)です。

_CREATE TABLE "tblReadings2013-10-01"
(
-- Inherited from table "tblReadings_master":  "sessionID" integer NOT NULL,
-- Inherited from table "tblReadings_master":  "fieldSerialID" integer NOT NULL,
-- Inherited from table "tblReadings_master":  "timeStamp" timestamp without time zone NOT NULL,
-- Inherited from table "tblReadings_master":  value double precision NOT NULL,
  CONSTRAINT "tblReadings2013-10-01_readingPK" PRIMARY KEY ("sessionID", "fieldSerialID", "timeStamp"),
  CONSTRAINT "tblReadings2013-10-01_fieldSerialFK" FOREIGN KEY ("fieldSerialID")
      REFERENCES "tblFields" ("fieldSerial") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT "tblReadings2013-10-01_sessionFK" FOREIGN KEY ("sessionID")
  REFERENCES "tblSessions" ("sessionID") MATCH SIMPLE
  ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT "tblReadings2013-10-01_timeStamp_check" CHECK ("timeStamp" >= '2013-10-01 00:00:00'::timestamp without time zone AND "timeStamp" < '2013-11-01 00:00:00'::timestamp without time zone)
)
_

すでに収集されているデータをテーブルに入力する処理を行っています。各ファイルは約48,000ポイントのトランザクションを表し、数千のファイルがあります。これらはINSERT INTO "tblReadings_master" VALUES (?,?,?,?);を使用してインポートされます

最初にファイルは1000以上の挿入/秒の速度でインポートされますが、しばらくすると(一貫性のない量ですが、30分程度を超えることはありません)、この速度は10〜40挿入/秒に急降下し、PostgresプロセスRails CPU。元のレートを回復する唯一の方法は、完全なバキュームを実行して分析することです。これは、最終的に月次テーブルあたり約1,000,000,000行を格納するため、バキュームには時間がかかります。

編集:これは、小さなファイルでしばらく実行され、大きなファイルが開始された後に失敗した例です。ファイルが大きいほど不規則に見えますが、トランザクションがファイルの最後(約40秒)でのみコミットされるためだと思います。 CPU and Insert trace of problem

一部のアイテムを選択するWebフロントエンドがありますが、更新や削除はありません。これは、他のアクティブな接続がない場合に発生します。

私の質問は:

  1. CPUのスローダウン/レイルの原因を知るにはどうすればよいですか(これはWindowsにあります)?
  2. 本来の性能を維持するために何ができるでしょうか?
8
jamesmc86

この問題の原因となっている可能性があるものはいくつかありますが、それらのいずれかが本当の問題であるかどうかはわかりません。トラブルシューティングはすべて、データベースで追加のロギングをオンにして、遅い部分がそこにメッセージと並んでいるかどうかを確認することを含みます。 log_line_prefix設定にタイムスタンプを入れて、役立つログを確認してください。ここから始めるために私の調整の紹介を見てください: https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

Postgresはすべての書き込みをオペレーティングシステムキャッシュに行い、後でディスクに書き込みます。これは、log_checkpointsをオンにしてメッセージを読み取ることで確認できます。処理が遅くなると、すべてのキャッシュがいっぱいになり、すべての書き込みがI/Oの最も遅い部分を待機してスタックする場合があります。 Postgresチェックポイント設定を変更することで、これを改善できる場合があります。

大量の挿入がデータベースでのロックを待機してスタックする場合があるデータベースヒットの内部問題があります。 log_lock_waitsをオンにして、ヒットしているかどうかを確認します。

システムの自動バキュームプロセスが開始されると、バースト挿入を実行できるレートが維持できるレートよりも高い場合があります。log_autovacuumをオンにして、問題が発生したときに同時に発生するかどうかを確認します。

データベースのプライベートshared_buffersキャッシュにある大量のメモリは、Windowsでは他のオペレーティングシステムと同じように機能しないことがわかっています。それが発生したときに何が問題になるのかについて、それほど多くの可視性はありません。私は、Windows PostgreSQLデータベースに1秒以上挿入する1000以上を実行するものをホストしようとはしません。これは、まだ非常に大量の書き込みに適したプラットフォームではありません。

5
Greg Smith

私はPostgresのエキスパートではないので、これは間違っているかもしれません!主キーには3つの列があり、最初のフィールドはsessionIDです。ファイルにはタイムスタンプのまともな広がりが含まれていますか?現在、これはかなり広いため、主キーの最初のフィールドを作成するか、代理キーを使用することを検討する場合があります。

あなたのスクリプトから、私はあなたがクラスターを持っているとは思いません。 SQL Serverとは異なりますが、 'Cluster'コマンドを使用してPostgresのテーブルの物理的な順序を指定する必要があると思います。リンクはこれについて話します:

https://stackoverflow.com/questions/4796548/about-clustered-index-in-postgres

0
DamagedGoods