私たちは平均 10,000 人のアクティブ ユーザーを持つ Web アプリケーションを実行しており、6 つの Web ノードによってサービスを提供され、Postgres 9.4.6 によって支えられています。
私たちの監視ツールは、以下の実行速度の遅いクエリを特定しました。このクエリは、応答時間が許容できないことが多く、過去数日間で時折停止を引き起こしました。
これは小さなテーブルで、基本的に社内シーケンス実装 (レガシー アプリケーション) であり、他のテーブルごとに一意の ID を追跡します。
CREATE TABLE ids_for_records
(
tableid integer NOT NULL,
id bigint NOT NULL,
CONSTRAINT ids_for_records_pk PRIMARY KEY (tableid)
)
WITH (
OIDS=FALSE
);
このテーブルには約 200 レコードしかありません。私たちの webapp ノードは、このクエリを使用して、使用する専用の ID のバッチを取得します。
UPDATE ids_for_records
SET id = id + <batchsize>
WHERE tableid = <unique-internal-table-id>
RETURNING id;
上記のクエリのパフォーマンスが過去数日間で大幅に低下した理由を突き止める必要があります。平均で約 1 秒ですが、30 ~ 60 秒かかることもあります。高負荷時には、すべてのノードが複数の接続に対してまったく同じクエリを並行して実行しています。
UPDATE : 単一の (遅い) クエリによって保持されている (pg_lock、pg_class、および pg_stat_activity からの) ロックに関する情報を照会すると、待機中の他のトランザクションからのまったく同じクエリであることが示されました。そのため、同じ行を更新 (ID 値をインクリメント) しようとする同時トランザクションがあるため、必要なすべてのロックでアクティブな 1 つが他のすべてをブロックします。
それ以外の場合、データベースは正常です。運用チームは、ストレージ、メモリ、または接続に関してまったく問題を発見しませんでした。ただし、別のテーブルのサイズが最近 64GB に達したため、関連している可能性があります。
このようなパフォーマンスの低下を引き起こす可能性のあるものは誰にも分かりますか? 以前と同じ負荷ですが、このボトルネック クエリは以前よりも 5 倍遅くなります。