PostgreSQL 9.0 の新機能
NTT オープンソースソフトウェアセンタ 板垣 貴裕
※記事内では、PostgreSQL8.5 とありますが、その後次のメジャーバージョンは 9.0 になることが決定しました。タイトルのみ変更しておりますが、本文は 8.5 という表記のままにしています。
2009年12月20日、PostgreSQL 8.5 の開発マイルストーン版である Alpha 3 がリリースされました。アルファ版は "Alpha Information" からダウンロードできます。
Alpha 3 ではホット・スタンバイ機能が採用され、「参照負荷分散レプリケーション」を構成する準備が整いつつあります。また、それ以外にも既に数多くの新機能が採用されています。この記事では、完成間近の参照負荷分散レプリケーションの概要と、その他の PostgreSQL 8.5 の新機能について紹介します。
参照負荷分散レプリケーション
PostgreSQL 8.5 には「ホット・スタンバイ」が採用され、「ストリーム・レプリケーション」も継続して開発中です。これらを組み合わせることで、PostgreSQL でシングルマスタ - マルチスレーブ型の参照負荷分散クラスタが手軽に組めるようになる見込みです。
ホット・スタンバイ (Hot Standby)
ホット・スタンバイは v8.5 の大きな特徴になることが期待されている機能です。後述のレプリケーション機能と組み合わせることで、複数サーバ間で参照の負荷を分散できるクラスタ構成が使えるようになります。以前のバージョンでは「ウォーム・スタンバイ」として参照も更新もできなかった待機サーバを、参照用として有効活用できるようになります。参照のみと言っても、ソート用の作業ファイルは作成できるため、待機サーバで集計処理や pg_dump などの重い参照クエリを実行するのも良いでしょう。(ただし、一時テーブルは使えません。)
ホット・スタンバイの機能自体は「リカバリ処理中の参照クエリを許す」という一言で説明できるのですが、スタンバイ側で参照中のデータがプライマリで削除された場合の挙動など、細部まで気を配って対応されています。ログシッピングという物理的に完全に同じ状態を作る方式ですので、レプリケーションが完了した領域のデータの構造は完全に一致しています。このため、ユーザから見たデータベースは常に一貫した状態に保たれます。もちろん、プライマリ側で行った VACUUM 処理も転送されますから、スタンバイ側での特別な運用も要りません。
注意が必要なのは、ホット・スタンバイで待機サーバから得られる結果には時間的な遅れがあることです。過去のある時点での一貫性のある結果は取得できますが、ログの適用が遅延していると最新の情報は取得できません。ただし、後述のレプリケーション機能と組み合わせることで、遅れは大幅に低減できる見込みです。また、リカバリ処理と競合するクエリが長時間続くと、強制的にキャンセルされる場合があります。キャンセルまでの待機時間は調整できますが、時間がかかるクエリをスタンバイ側で実行する場合には気をつけましょう。
参考- Hot Standby (PostgreSQL 8.5devel Documentation)
- Hot Standby (PostgreSQL Wiki)
ストリーム・レプリケーション (Streaming Replication)
8.5 Alpha 3 の時点では、ストリーム・レプリケーションは採用されていません。この記事は、提案中の開発版に基づいて執筆しています。
組み込みのレプリケーションも採用される見込みです。以前のバージョンでもアーカイブログを転送して別サーバで逐次ログを適用する「ウォーム・スタンバイ (warm standby)」が利用できましたが、ストリーム・レプリケーションには以下の利点があります。
v8.5 のレプリケーションの利点- トランザクションログの転送が、ファイル単位では無く、操作単位で行われるため、遅延が少ない。
- 複数のスタンバイ・サーバへ転送できる。
- スタンバイ・サーバはいつでも追加 / 切り離しでき、追加の際の静止点は不要。
- スタンバイ側で適用済みのトランザクションログを自動的に削除できる。
- PostgreSQL 本体と協調して動作するため、管理に手間がかからない。
また、現時点ではログの転送は遅延がありますが、8.5 の正式リリースまでには「遅延なし」に転送するオプションも追加される見込みです。プライマリ側でのレスポンスには若干の悪影響があるものの、フェイルオーバー時にもトランザクションの結果を全て引き続くことができるようになるため、信頼性が要求されるシステムで役立つでしょう。
参考: Streaming Replication (PostgreSQL Wiki)
既存のレプリケーション製品との関係
ホット・スタンバイ + ストリーム・レプリケーションの組み合わせを使うと、多くの用途で満足できるかと思いますが、それでもまだ足りない点も残っています。
v8.5 のレプリケーションだけでは実現できないこと- 自動的に参照を分散する機能が無い。
- プライマリの故障時に自動的にフェイルオーバーする機能が無い。
- クラスタ間でメジャーバージョンを統一する必要がある。(マイナーバージョンの違いは可)
- データベース全体のみ複製できる。一部だけの複製やデータの分割は不可。
そのため、既存のレプリケーション製品も、用途によっては もしくは v8.5 のレプリケーション機能と組み合わせて、今後も使っていくことになるでしょう。
- pgpool
- 参照を分散する機能は依然として有効です。レプリケーションは 8.5 機能に任せ、pgpool でクエリを分散させるという構成が考えられます。
- Slony-I
- データの一部だけの複製ができるのは Slony-I の利点です。また、SQLベースの複製を行うため、メジャーアップグレードの際に pg_dump の代わりに使えるのは Slony-I だけです。
- PGCluster, PL/Proxy
- データの分割には PGCluster や PL/Proxy のような仕組みが必要です。
- Heartbeat などの監視ミドルウェア
- ダウンタイムを減らすには、フェイルオーバやプライマリへの昇格を自動化する監視ミドルウェアを組み合わせる必要があります。
What's New in 8.5
Alpha 3 までに採用された新機能を一覧で紹介します。 Alpha 2 から 3 の差分には ★ で印をつけています。 SQL 構文やログ出力機能を中心に改善が進んでいます。
性能
- ★ ALTER TABLE でのテーブル再構成で WAL をスキップ
- archive_mode が off の場合に限られますが、ALTER TABLE で列の型変更など、テーブルを再構成する際に無駄な WAL を出力しないようになりました。再構成の高速化が期待できます。
- オプティマイザ:利用されない JOIN の削除
- JOIN されるテーブルがあっても、データを取得しなければ JOIN 対象から外す最適化が行われるようになりました。特に LEFT JOIN を利用するビューで役立ちます。以下の例では、tbl_right のスキャンを省略できていることがわかります。
=# CREATE TABLE tbl_left (id integer, a text);
=# CREATE TABLE tbl_right (id_ref integer UNIQUE, b text);
=# CREATE VIEW tbl AS
SELECT * FROM tbl_left LEFT JOIN tbl_right ON id = id_ref;
=# EXPLAIN SELECT id, a FROM tbl;
=> Seq Scan on tbl_left
セキュリティ
- ★ ALTER LARGE OBJECT: ラージオブジェクトのアクセス制御
- ラージオブジェクトに所有権と読み書きのアクセス制御ができるようになりました。そのための構文 ALTER LARGE OBJECT, GRANT/REVOKE LARGE OBJECT も追加されています。
- GRANT/REVOKE ON ALL TABLES/SEQUENCES/FUNCTIONS IN SCHEMA
- 指定したスキーマに含まれるオブジェクトのアクセス権を一括で変更できます。
- ★ passwordcheck モジュールの導入
- 推測されにくいパスワードのみを許可できるフィルタが追加されました。デフォルトの設定では 8 文字以上かつアルファベットと非アルファベットの組み合わせからなるパスワードだけを許します。
- ALTER DEFAULT PRIVILEGES
- 将来に作成されるオブジェクトに対するアクセス権限のデフォルト値を設定できるようになりました。
SQL
- ★ EXCLUDE 制約 (Exclusion constraints)
- 排他制約 (EXCLUDE) は、一意性制約 (UNIQUE) を一般化した PostgreSQL の独自機能です。指定した演算子を満たす行は、テーブル中に1行しか存在できません。特に地理情報 (GIS) を扱う場合に、地図上のオブジェクトが重なっていないことを保障するのに便利です。
- ★ CREATE TRIGGER ... WHEN (...)
- 条件付きトリガがサポートされました。特に、特定の列が変更された際にのみ起動されるようにするためには
new.* IS DISTINCT FROM old.*とします。UPDATE OF との違いは、実際に値が変更された場合にのみ起動されることです。 - ★ EXPLAIN (ANALYZE, BUFFERS)
- EXPLAIN ANALYZE で実際の動作を解析する際に、バッファアクセス状況を追加で取得できるようになりました。共有バッファ、一時テーブル、ソート領域のキャッシュヒット数や I/O 回数が表示されます。スロークエリの原因が、I/O 回数なのか、メモリアクセス回数なのか、ソート用メモリ不足なのか、といった解析に役立ちます。
- ★ EXPLAIN ( format { text | xml | json | yaml } )
- EXPLAIN の出力を、これまでのテキスト形式に加えて、XML, JSON, YAML 形式で取得できるようになりました。人間が読みやすいのはテキスト形式ですが、もし実行計画を画像として表示するようなツールを作る場合には、これらの構造化された書式が便利でしょう。
- function( 'value' AS name )
- 関数のデフォルト引数を名前与えて値を設定できるようになりました。複数のデフォルト引数を持つ場合に、その一部のみに値を設定したい場合に役立ちます。
=# CREATE FUNCTION func(
a integer,
b integer DEFAULT 2,
c integer DEFAULT 3
) RETURNS text AS
$$ SELECT 'a=' || $1 || ', b=' || $2 || ', c=' || $3 $$
LANGUAGE sql IMMUTABLE STRICT;
=# SELECT func(1); ⇒ a=1, b=2, c=3
=# SELECT func(1, 8, 9); ⇒ a=1, b=8, c=9
=# SELECT func(1, 9 AS c); ⇒ a=1, b=2, c=9 - ALTER ROLE role IN DATABASE database SET param TO value
- ユーザとデータベースの組み合わせごとに設定パラメータを指定できるようになりました。設定値は psql からならば、メタコマンド
\drdsで確認できます。 - ALTER TABLE ... ADD { UNIQUE | PRIMARY KEY } (...) DEFERRABLE
- UNIQUE 制約に DEFERRABLE オプションを指定できるようになりました。一意性の確認はトランザクションのコミット時まで先送りにされるため、一時的に一意性制約の違反になるような変更も許されます。(例: UPDATE ... SET id = id + 1)
- ALTER TABLE ... ALTER COLUMN ... SET STATISTICS DISTINCT
- 列ごとのカーディナリティ統計情報を強制的に固定値に設定できるようになりました。PostgreSQL の統計情報収集ロジックが上手く働かない場合のチューニング手段です。
- ALTER TABLE ... ALTER COLUMN ... SET STORAGE MAIN
- 列ごとのストレージ・オプション MAIN の効果が変更され、その列が TOAST 領域に追い出されるのを防止できるようになりました。行サイズが 2KB 以上になる場合のチューニング手段です。
- COPY tbl TO 'file' WITH CSV FORCE QUOTE *
- 全ての列をダブルクォート " " で囲むオプション FORCE QUOTE * が追加されました。
- CREATE TABLE ... (LIKE parent INCLUDING { COMMENTS | STORAGE | ALL } )
- テーブル定義の際、LIKE INCLUDING オプションに COMMENTS と STORAGE が追加されました。それぞれ、コメントやストレージパラメータをコピーします。また、ALL を指定するとすべての INCLUDING オプションを指定したのと同じ効果になります。パーティションを定義する際には、この ALL オプションを使うと手間が省けるでしょう。
- CREATE TRIGGER ... UPDATE OF column
- 列トリガがサポートされました。指定した列を変更の対象に選択した場合にのみトリガ関数が呼ばれます。実際には値が変更されなくても、UPDATE の SET 句に指定された場合には起動されることに注意が必要です。
- DO 'code'
- 関数を作成せずにインラインで手続き言語 (PL/pgSQL 等) を実行できます。クエリの結果を元に DDL を発行するような場合に、スクリプトファイルを作る代わりに使えます。
- DROP { COLUMN | CONSTRAINT } IF EXISTS
- 列や制約に対して DROP 対象が存在しなくてもエラーにしない IF EXISTS オプションが追加されました。
ログ関連
- log_line_prefix に %e (SQLSTATE) が追加
- エラーコードをログに出力できます。8.4 以前では log_error_verbosity = verbose にしなければなりませんでした。
- 一意性制約の違反時に列の値を出力
- 一意性制約のある列の変更時やユニーク・インデックスの作成時に、制約違反があった列の値をログに出力するようになりました。
=# UPDATE tbl SET id = 1 WHERE id = 2;
ERROR: duplicate key value violates unique constraint "tbl_pkey"
DETAIL: Key (id)=(1) already exists. - pg_ctl reload した際に変更があったパラメータをログに出力
- どのパラメータが変更されたかが分かりやすくなりました。
- Windows のイベントログやコンソール出力の文字化け修正
- PostgreSQL で日本語を扱う場合、サーバエンコーディングには UTF-8 または EUC_jp を選ばなければなりません。しかし、Windows のイベントログやコンソールではエンコーディングを SJIS にして出力する必要があるため、サーバログが文字化けしていました。v8.5 ではログをユニコードで出力するようになり、この問題が解消されています。
その他
- ★ pgbench に \shell, \setshell メタコマンドが追加
- pgbench からシェルコマンドを実行し、結果を変数に格納するメタコマンドが追加されました。複雑な機能試験や負荷試験に利用できるでしょう。
- ★ クライアント・アプリケーション名の表示
- 設定パラメータ application_name を使ってクライアント・アプリケーション名を表示またはロギングできるようになりました。libpq で接続を行うアプリケーションでは、環境変数
PGAPPNAMEを使って初期値を設定できます。この機能はセキュリティ用途ではなく、単にプロセス一覧やログを読みやすくする機能です。アプリケーション名の指定の強制や詐称の防止、特定のアプリケーションの拒否といったことはできません。 - ★ pg_ctl init[db] モードの追加
- pg_ctl に init 及び initdb モードが追加されました。以下は同じ意味になります。
$ pg_ctl initdb -o "--locale=C --encoding=UTF8"
現時点では initdb コマンドと全く同じですが、将来的に名前が pg_ から始まるコマンドに統一される可能性があるため、この書式に移行を始めても良いかもしれません。
$ initdb --locale=C --encoding=UTF8 - ★ PL/Python 3 の追加
- 手続き関数で Python 3 がサポートされました。これまでの Python 2系 (plpythonu) とは別の、plpython3u の名前で登録されています。
- pg_hba.conf で samehost, samenet をサポート
- サーバと同じアドレスからの認証を一括で設定します。サーバが動的なアドレスを持つ場合に役立ちます。
- pgbench -j スレッド数
- pgbench がマルチスレッド化され、CPUが複数ある環境でも十分な負荷をかけられるようになりました。これまでは pgbench 自体がボトルネックになり、サーバの性能を引き出せない場合がありました。スレッド数は pgbench を実行するマシンの CPU 数程度に設定すると良いようです。
PostgreSQL 8.5 の開発のされ方
バージョン 8.4 に引き続き、CommitFest というパッチの採用枠を区切りながら開発が進められています。開発に関する議論は旧来どおりメーリングリストで行われていますが、投稿されたパッチの管理には CommitFest Management と呼ばれるウェブ・アプリケーションが新規に開発されました。
また、リリースごとに Alpha リリースを行うようになり、ユーザからのフィードバックを受けやすい環境づくりが始まりました。8.4 ではリリースが大幅に遅れたことに反省し、リリース期日を守れるよう運営されています。
| リリース名 | リリース日 |
|---|---|
| 8.5 Alpha 1 | 2009-08-20 |
| 8.5 Alpha 2 | 2009-10-24 |
| 8.5 Alpha 3 | 2009-12-20 |
| 8.5 Alpha 4 | 2010-02-20 |
| 8.5 Beta 1 | 2010-03-xx |
| 8.5.0 | 2010-06-xx |
まとめ
PostgreSQL 8.5 は、レプリケーションを始め、機能強化が著しいリリースになりそうです。
外部リンク
8.5 のリリースと開発版に関する情報の収集には、以下のサイトが参考になります。
- PostgreSQL 8.5alpha2 Now Available
- PostgreSQL 8.5 リリースノート
- CommitFest Management
- Waiting for 8.5 (新機能ウォッチblog)



