web-dev-qa-db-ja.com

時折/断続的、遅い(10秒以上)UPDATEクエリがGINインデックスを持つPostgreSQLテーブルで

セットアップ

Debian Linux(8)を搭載したSSDベースのクアッドコア仮想プライベートサーバー(VPS)でPostgreSQL 9.4.15を実行しています。関連するテーブルには、約200万件のレコードがあります。

レコードが頻繁に挿入され、さらに頻繁に(少なくとも数秒ごとに)更新されます。私の知る限りでは、これらの操作を迅速に実行するために適切なすべてのインデックスを用意していますが、それらのほとんどの時間は瞬時に実行されます(ミリ秒単位)。

問題

ただし、約1時間ごとに、UPDATEクエリの1つは、10秒以上など、過度に時間がかかります。そして、これが発生すると、それは通常、「ブロック」されるクエリの「バッチ」のようなものであり、すべてがほぼ同時に終了します。クエリの1つ、または他のバックグラウンド操作(バキュームなど)がすべてをブロックしているようです。

スキーマ

テーブルitemsには多くの列がありますが、問題に関連する可能性があるのは次のものだけだと思います。

  • _id INTEGER NOT NULL_(主キー)
  • _search_vector TSVECTOR_
  • _last_checkup_at TIMESTAMP WITHOUT TIME ZONE_

そして、これらは関連するインデックスです:

  • items_pkey PRIMARY KEY, btree (id)
  • items_search_vector_idx gin (search_vector)
  • items_last_checkup_at_idx btree (last_checkup_at)

犯人らしい

最後に、「接続リーク」警告がログファイルに出力されるたびに_pg_stat_activity_(すべてのアクティブなPostgres接続/クエリのリスト)の内容をダンプする小さなスクリプトを一緒にリギングした後、考えられる原因のクエリ/列(問題がVPSの誤動作のように外部にあるものではないと想定)。大まかに言って、これらは何度も何度も表示されるように見えるクエリの種類です。

  • _UPDATE items SET last_checkup_at = $1 WHERE items.id = 123245_
  • _UPDATE items SET search_vector = [..] WHERE items.id = 78901_

それらは少し言い換えられていますが、関連するものが欠けていることは間違いありません。 (他のテーブルで)他のクエリが表示されることもありますが、それらは通常、その組み合わせに巻き込まれるのが「不運」だったように見えます。

現在、最初のクエリ(_last_checkup_at_の設定)はほとんどの場合に表示される傾向がありますが、_search_vector_を設定するクエリはevery時間のように見えます。 (それに加えて、一般的に発行される最初のクエリのインスタンスはおそらくさらに多くあり、偶然に存在する可能性が高くなります。)

(私はここで解決策を知っていると思いますが、それをバッグに入れていても、他の人のためにここでインシデントを文書化したかったのです...ディープダイブ。)

2
Chris W.

問題はPostgresの「FASTUPDATE」メカニズムにあるようです。

FASTUPDATEGINインデックスで使用可能な設定 であり、これを有効にすると、インデックス(UPDATEsとおそらくINSERTsによっても引き起こされる)が "キューに入れられる"ようになります。次に、この「キュー」が大きくなりすぎると、保留中のエントリがGINインデックスに適切に統合されます。

FASTUPDATEの目的は、インデックスの更新を高速化すること(驚きではありません)ですが、残念ながら、時折UPDATEクエリが非常に遅くなります。私の場合、ヒットを前もって取得することをお勧めします(主に、ログの「遅いクエリ」の警告を回避するため)。

FASTUPDATEは明らかにデフォルトで有効になっており、PostgreSQL 8.4以降で使用できます。私は次のようにそれを無効にすることができました:

ALTER INDEX items_search_vector_idx SET (FASTUPDATE=OFF);

これを書いている時点で、私はほぼ1週間もそのように実行しており、遅いクエリはほとんどありません。 (時間がかかると思われるクエリは別として、他にはほとんど気づきませんでした。)

また、Postgresメーリングリストの 関連するスレッド で関連情報を見つけることもできます。興味深いことに、Postgres開発者の1人(Tom Lane)は、FASTUPDATEの保留中のアイテムの処理を「同時挿入をブロックすることは想定されていなかった」と示唆していますが、それが正しいかどうかはわかりません。私の場合、いくつかのクエリが「バックアップ」され、すべてが一度に完了するのがわかります。

5
Chris W.