一つ前のメジャーリリースであるPostgreSQL 9.3から、マテリアライズドビュー機能が導入されました。マテリアライズドビューとは、検索結果を記憶しておく機能を持ったビューです。
時間が掛かる集計処理などに、通常のビューの代わりに適用して、検索処理の負荷を節約するといった使い方がされます。このとき、記憶されている検索結果を更新するには、明示的にREFRESH MATERIALIZED VIEWコマンドを実行する必要がありました。
PostgreSQL 9.3のマテリアライズドビュー実装では、ここに一つ問題がありました。REFRESH MATERIALIZED VIEWコマンドは、対象のマテリアライズドビューに対して、AccessExclusiveという、最も強いモードのテーブルロックを取得してしまうのです。その結果、リフレッシュ処理途中のマテリアライズドビューに対するSELECTコマンドは、リフレッシュが終わるまで待たされてしまいます。
リフレッシュが短時間で終わるならばよいですが、長時間を要するケースでは、マテリアライズドビューを参照する処理が長く待たされてしまい、問題になります。そもそも実行に時間が掛かるSELECTコマンドであったからこそ、マテリアライズドビューにしたかったはずなので、これでは本末転倒になってしまうわけです。
そこで、PostgreSQL 9.4ではREFRESH MATERIALIZED VIEWコマンドにCONCURRENTLYという、リフレッシュ中にもアクセス可能にするオプションが追加されました。このコマンドオプションはExclusiveという、一段階弱いモードのロックしか取得しません。このため、対象マテリアライズドビューに平行してSELECTコマンドを実行できます。リフレッシュ中に実行されたSELECT命令には、以前のデータが返ります。
CONCURRENTLYオプションを使うには、マテリアライズドビューに対する主キーやユニークインデックスが少なくとも一つ定義されている必要があります。
以下に使用例を示します。
db1=# CREATE MATERIALIZED VIEW mv_date_sales_ammount AS SELECT to_char(ts, 'YYYY-MM-DD')::date as date, sum(ammount) FROM t_sales GROUP BY date; ⇒ タイムスタンプ ts、売上金額 ammount のカラムを持つ、 テーブル t_sales にマテリアライズドビューを定義 db1=# CREATE UNIQUE INDEX ON mv_date_sales_ammount (date); ⇒ ユニークインデックスを作成しておく db1=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_date_sales_ammount; ⇒ これで CONCURRENTLY オプションでのリフレッシュが使える
PostgreSQL 9.4では、ALTER TABLEコマンドに対してもロック待ちを軽減する改修が行われています。
テーブル定義を変更するALTER TABLEコマンドは、並行するSELECTコマンド実行をブロックするAccessExclusiveモードのロックを必要とします。テーブルにカラムを追加したり、データ型を変更するとなれば仕方のないところです。しかし、ALTER TABLEコマンドのオプション指定の中には明らかにテーブル内のデータへのアクセスを制限する必要性に乏しいものがありました。
このため、PostgreSQL 9.4からは、以下表のALTER TABLEオプションについて、データ読み書きと競合しない弱いロックモードに変更されました。
ALTER TABLE のオプション | 意味 |
---|---|
VALIDATE CONSTRAINT | 制約を検証する |
CLUSTER ON | クラスタ化で使うインデックスを指定 |
SET WITHOUT CLUSTER | クラスタ化で使うインデックス指定を解除 |
ALTER COLUMN SET STATISTICS | 統計情報収集について調整 |
ALTER COLUMN SET (...) | カラム単位オプションを指定 |
ALTER COLUMN RESET (...) | カラム単位オプション指定を解除 |
表2 ロックモードが変更されるALTER TABLEコマンドのオプション
Copyright © ITmedia, Inc. All Rights Reserved.