web-dev-qa-db-ja.com

書き込み集中型データベースでのPostgreSQLパフォーマンスの経時的な低下

時間の経過とともにクエリ(以下で説明するクエリの組み合わせ)のパフォーマンスが低下するという奇妙な状況を観察しました。つまり、テストの開始時(数分間)にクエリの時間が2ミリ秒で、翌日は15ミリ秒に達しました。その後30ミリ秒後。

クエリでは、次のいずれかの組み合わせを参照します。

  • テーブル2に行を挿入し、テーブル2から行を選択し、テーブル3の行を選択し、テーブル3の行を更新し、コミットします。
  • 表1に行を挿入し、表3の行を選択して、表3の行を更新し、コミットします。

その理由は何なのか、または構成ファイルのどの設定をどのように検討する必要があるのでしょうか?データベースが設定されていて、主キーが追加されていないUbuntuマシンで問題が発生しました。一方、私が開発したWinは観察されませんでした(7日間、クエリあたり平均3msで常に実行されていました)。

新しいデータベース(Ubuntu)では、私が開発したものとは対照的に、どのテーブルにも主キーがないことに気付きました。 主キーの欠如は、この種のクエリに悪影響を及ぼしますか?

開発マシンからテストマシンにデータベース全体を移動している間、この質問をするつもりでした。

開発時にはPostgreSQL 8.4(CPU:Intel i7 740QM、RAM:6GB)を使用しましたが、テストではPostgreSQL 9.1(CPU:Intel i3-2100、RAM:3.8GB)があります。


PDATE:autovacuum関連パラメーター:

#autovacuum = on        
#log_autovacuum_min_duration = -1   
#autovacuum_max_workers = 3     
#autovacuum_naptime = 1min      
#autovacuum_vacuum_threshold = 50   
#autovacuum_analyze_threshold = 50  
#autovacuum_vacuum_scale_factor = 0.2   
#autovacuum_analyze_scale_factor = 0.1  
#autovacuum_freeze_max_age = 200000000  
#autovacuum_vacuum_cost_delay = 20ms    
#autovacuum_vacuum_cost_limit = -1  

PDATE2:開発マシンでも問題が発生しているようですが、以前は問題なく動作していたことを覚えています。少し時間をかけてテストを実行し、クエリに対してEXPLAIN ANALYZEを実行しましたが、それが更新であることに変わりはありません(テーブルでの選択にも時間がかかることがわかりました)。

EXPLAIN ANALYZE UPDATE ais_track SET latest_dynamic = '2012-09-10 22:22:22.222' WHERE mmsi = 123456789 AND ais_system = 1;

以下の結果は、Ubuntuで復元がまだ進行中であるWinでの結果です。

Index Scan using pk_track on ais_track  (cost=0.00..4.46 rows=1 width=36) (actual time=1.090..2.460 rows=1 loops=1)
  Index Cond: ((mmsi = 123456789) AND (ais_system = 1))
Total runtime: 8.681 ms

次に、同じ更新クエリを2回繰り返し、さらに数回繰り返して、次のような形式を取得します。

Index Scan using pk_track on ais_track  (cost=0.00..4.46 rows=1 width=36) (actual time=0.699..1.797 rows=1 loops=1)
  Index Cond: ((mmsi = 123456789) AND (ais_system = 1))
Total runtime: 1.850 ms

100回ほど繰り返した後、2ms以上になりました。

SelectのEXPLAIN ANALYZE:

EXPLAIN ANALYZE SELECT * FROM ais_track WHERE mmsi = 123456789 AND ais_system = 1

1回目の実行:

Index Scan using pk_track on ais_track  (cost=0.00..4.46 rows=1 width=38) (actual time=1.283..2.522 rows=1 loops=1)
  Index Cond: ((mmsi = 123456789) AND (ais_system = 1))
Total runtime: 2.560 ms

100ほど実行した後:

Index Scan using pk_track on ais_track  (cost=0.00..4.46 rows=1 width=38) (actual time=0.027..1.357 rows=1 loops=1)
  Index Cond: ((mmsi = 123456789) AND (ais_system = 1))
Total runtime: 1.382 ms

クエリで使用されるテーブル:

CREATE TABLE ais_track
(
  ais_system integer NOT NULL,
  mmsi integer NOT NULL,
  ext_id integer,
  latest_dynamic timestamp without time zone,
  latest_static timestamp without time zone,
  "name" character varying,
  CONSTRAINT pk_track PRIMARY KEY (mmsi, ais_system)
)

そして2つのインデックス:

CREATE INDEX ais_track_mmsi
  ON ais_track
  USING btree
  (mmsi);

CREATE INDEX ais_track_sys
  ON ais_track
  USING btree
  (ais_system);

注:テーブルのサイズは11000で、変更されません

5
Boro

@Frank Heikens、@ dezso、および@Colin 't Hartに、提案と関与をありがとう。

問題は、私が MyBatis を使用していた方法にありました。私は「特別な」:)シングルトンパターンを使用しましたが、これは必要に応じて新しいインスタンスを生成することができ、いくつかの一般的なもののために1つの共有接続を持ちました。私の質問で述べた操作のために、私は接続の新しいインスタンスを使用していました。

どうやら、これは共有接続を使用するのは良い考えではありません。私の経験が示すとおり、MyBatisのマニュアルでは、作業が完了した後に接続(セッション)を閉じるように促すことで提案しています。とにかく問題は、最初に共有接続を使用してデータベースから静的テーブルをロードし、その後、単一選択を行った後、接続が使用されなかったことでした。私がクエリを作成しているとき、つまりais_trackテーブルで選択して更新しているときは、操作の時間が増加していました。共有接続を正確に閉じなかったため、別の接続でクエリが実行され、実行ごとに速度が低下したのはなぜでしょうか。提案があれば教えてください。

プレーンJDBCを使用しているときは、この問題を再現できませんでした。それで、MyBatisと関係があるのではないかと思いますか、それとも私はそれを正しく使用していませんか?

私の解決策は共有リソースを取り除くことでした、そして私がいくつかの操作を行い、接続を使用しなくなったらそれを閉じます。また、選択した後に共有接続を使用してコミットを強制した場合、それがまだ開いたままになっている場合でも問題が発生しなかったことにも気付きました。

BTW:シングルトンを使用することが悪い理由がある場合、そして最も重要な場合はコメントを付けてください。つまり、 dbへの接続がハングしている(実際に私が言っていることが真実である場合)。-

3
Boro

All(?)RDBMSの主キーと一意キーは、新しく挿入された値が実際に一意であるかどうかをすばやく判断できるように、インデックスを使用します。

これの副作用は、主キーと一意のキーを介したクエリが通常「高速」であることです。

テーブルに主キーまたは一意のキーを定義していない場合は、

  1. リレーショナルテーブルはありませんが、ジャンクがあります(これは論争の的ですが、リレーショナルモデルではすべてのテーブルにキーが必要です)。
  2. このテーブルに対するクエリ(他のインデックスがない場合)は、テーブルに挿入されるデータが増えるほど遅くなります。

つまり、主キーがないと、これが発生します。

5
Colin 't Hart