$Id$

リリース日:2005/11/08

掲載日:2005/12/08

PostgreSQL 8.0.4から8.1の変更点

本ドキュメントはPostgreSQLのリリースノートおよびその翻訳版を元に作成しています。なお、ブランチが枝分かれしたのが8.0.3のため、いくつかの変更点は8.0.4と重複しています。

概要

このリリースの主な変更点を以下に示します。

共有バッファキャッシュへの同時アクセスの改良(Tom)

共有バッファキャッシュへのアクセスが、特に、マルチCPUシステムにおいて深刻なスケーラビリティ問題であることは分かっていました。 本リリースでは、バッファマネージャ内で行われていたロックの方法を見直し、ロックの競合を軽減し、スケーラビリティを向上しました。 また、バッファマネージャは"clock sweep"置換ポリシーを使用するように変更されました。

CPU数4個のマシンで同時接続数10以上のとき40%程度の性能アップが測定されています。

インデックススキャンが中間でメモリ内ビットマップを使用することができるようになりました。

過去のリリースでは、テーブル検索の実行において単一インデックスのみを使用することができました。 この機能により、WHERE tab.col1 = 4 and tab.col2 = 9を持つ問い合わせで、col1col2に対する複数列インデックスが存在しない場合、col1に対するインデックスとcol2に対するインデックスがあれば、両方のインデックスを検索し、結果をメモリ内で組み合わせ、col1col2に関する両方の制約に一致する行のみをヒープから取り出すことができるようになります。 これは、問い合わせが構造化されておらず、すべての起こり得るアクセス条件に一致するインデックスを前もって作成できないような状況では、非常に有用です。 必要なランダムアクセスの総数を減少させるため、ビットマップスキャンは単一のインデックスの場合でも有用です。 ビットマップインデックススキャンはテーブル全体で多くの割合を占める部分を取り出す際に効率的です。 この場合、通常のインデックススキャンでは非効率的です。

以下に例を示します。BitmapAnd、BitmapOr、Bitmap Heap Scan などの新しいクエリオペレータが使われます。

CREATE TABLE enquate (uid int,
  q1 int, q2 int, q3 int, q4 int, q5 int, value char(60));

INSERT INTO enquate SELECT i,
  (random()*2)::int, (random()*2)::int, (random()*2)::int, (random()*2)::int,
  (random()*2)::int  FROM generate_series(1, 100000) AS i;

CREATE INDEX iq1 ON enquate (q1);
CREATE INDEX iq2 ON enquate (q2);
CREATE INDEX iq3 ON enquate (q3);

=> EXPLAIN SELECT * FROM enquate WHERE q1 = 0 AND q2 = 0 AND q3 = 0;
                                  QUERY PLAN
------------------------------------------------------------------------------
 Bitmap Heap Scan on enquate  (cost=280.82..1365.68 rows=1519 width=228)
   Recheck Cond: ((q1 = 0) AND (q2 = 0))
   Filter: (q3 = 0)
   ->  BitmapAnd  (cost=280.82..280.82 rows=5935 width=0)
         ->  Bitmap Index Scan on iq1  (cost=0.00..137.65 rows=23900 width=0)
               Index Cond: (q1 = 0)
         ->  Bitmap Index Scan on iq2  (cost=0.00..142.92 rows=24833 width=0)
               Index Cond: (q2 = 0)
ニ相コミットの追加(Heikki Linnakangas, Alvaro, Tom)

二相コミットを使用して、トランザクションを複数のコンピュータで"準備"することができます。 すべてのコンピュータでトランザクションの準備を(失敗することなく)行った後、すべてのトランザクションをコミットすることができます。 準備した後でマシンがクラッシュしたとしても、マシンの再起動後に準備したトランザクションをコミットすることができます。 PREPARE TRANSACTIONおよびCOMMIT/ROLLBACK PREPAREDという新しい構文があります。 また、新しいpg_prepared_xactsシステムビューも追加されました。

一つのクライアントアプリケーションの実行コンテキストから複数のデータベースサーバに「一貫性を維持した」アクセスをしたいときに用いられます。準備されたトランザクションの識別名は定数文字列でないといけません。複数のクライアントから同時アクセスをする場合には識別名が重ならないように工夫が必要です。

=> BEGIN;
BEGIN
=> INSERT INTO booking (bdate, bname) VALUES (CURRENT_DATE, 'Yamada');
INSERT 0 1
=> PREPARE TRANSACTION 'x01-20051108-001';
PREPARE TRANSACTION
(ここでトランザクションの外に出る、以下は別セッションでもよい)
=> SELECT * FROM pg_prepared_xacts;
 transaction |       gid        |           prepared            | owner | database
-------------+------------------+-------------------------------+-------+----------
     1007867 | x01-20051108-001 | 2005-12-07 15:35:50.208045+09 | oss   |  oss
(1 row)
=> COMMIT PREPARED 'x01-20051108-001';
COMMIT PREPARED
ユーザとグループを置き換える、新しいロールシステムの作成(Stephen Frost)

ロールとは、ユーザとグループを組み合わせたものです。 ユーザのようにロールはログイン機能を持つことができますし、グループのようにロールは他のロールをメンバとして持つこともできます。 基本的にロールは、ユーザとグループの区別を取り除きました。 例えば、ロールは以下のことを行うことができます。

  • ログイン機能を有す(省略可能)

  • オブジェクトを所有する

  • データベースオブジェクトに対するアクセス権限を保持する

  • 属している他のロールの権限を継承する

ユーザがあるロールにログインした後、そのユーザはログインロールの能力の他、継承したロールの能力も持つことになります。 また、SET ROLEを使用して、属している他のロールに変わることもできます。 この機能は、標準SQLのロールの概念を汎用化したものです。 またこの変更により、pg_shadowpg_groupは、新しいロール機能の付いたカタログpg_authidpg_auth_membersに置き換わりました。 古いテーブルは、新しいロールテーブルに対する読み取りのみのビューとして再定義されています。

CREATE USER や CREATE GROUP などユーザ・グループの概念による旧来のコマンドはCREATE ROLEコマンドの別名という扱いになっています。表面的には互換性を保つように作られていますが、互換性目的のオプションは将来的には廃止が予定されています。また、ロールの導入に伴い「ユーザ(ロール)追加権限」と「管理者権限」が分離されました。管理者権限は持たないがロールの追加はできるロールを作ることができます。

MIN()MAX()におけるインデックスの自動使用 (Tom)

過去のリリースでは、MIN()またはMAX()でインデックスを使用する方法は、問い合わせをSELECT col FROM tab ORDER BY col LIMIT 1に書き換える方法しかありませんでした。 インデックスが自動的に使用されるようになりました。

例を示します。

=> EXPLAIN SELECT max(uid) FROM enquate;
                                            QUERY PLAN
--------------------------------------------------------------------------------------------------------
 Result  (cost=0.02..0.03 rows=1 width=0)
  InitPlan
   -> Limit  (cost=0.00..0.02 rows=1 width=4)
        -> Index Scan Backward using enquate_pkey on enquate  (cost=0.00..2302.00 rows=100000 width=4)
           Filter: (uid IS NOT NULL)
(5 rows)

8.0.x 以前ではインデックスが在っても以下のような「シーケンシャルスキャン+集約」になります。

                            QUERY PLAN
---------------------------------------------------------------------
 Aggregate  (cost=2231.00..2231.01 rows=1 width=4)
   ->  Seq Scan on enquate  (cost=0.00..1981.00 rows=100000 width=4)
(2 rows)
/contrib/pg_autovacuumを主サーバに移動しました。(Alvaro)

autovacuumをサーバに統合することで、データベースサーバと同期して自動的にautovacuumが起動、停止できるようになりました。 また、postgresql.confでautovacuumの設定を行うことができるようになりました。

autovacuum(自動バキューム)を利用するには行レベルアクセス統計情報が必要です。これは行の更新量を見てVACUUMする頃合いを決めるという仕組みになっているためです。行レベルの統計情報収集を行う(stats_start_collectorとstats_row_levelをtrueにする)場合、10%程度の性能低下があります。autovacuum利用には性能面でトレードオフがあります。

SELECT ... FOR SHAREを使用した共有行レベルロックの追加(Alvaro)

PostgreSQLのMVCCロックによりSELECTは書き込みによってブロックされることはありません。 そのため、通常の操作では共有行レベルロックは不要ですが、共有行ロックを必要とするアプリケーションでは共有ロックは有用です。 特に、これにより参照整合性検査で発生するロック要求が減少します。

共有ロックとは、排他ロック(更新、削除、FOR UPDATE)をブロックする/される一方、共有ロック同士では互いにブロックしないというものです。

共有オブジェクト、特にロールへの依存性を追加(Alvaro)

依存性機構の拡張により、データベースオブジェクトを所有するロールが削除されることを防ぎます。 これまでは、所有者の削除により"親のいない"オブジェクトができてしまう可能性がありました。 これは復旧させることができましたが、厄介で好まれないものでした。

以下、親のいないオブジェクトの例です。

oss=# CREATE USER foo;
CREATE USER
oss=# \c oss foo
You are now connected to database "oss" as user "foo".
oss=> CREATE TABLE foo (foo int);
CREATE TABLE
oss=> \c oss postgres
You are now connected to database "oss" as user "postgres".
oss=# DROP USER foo ; -- 8.1ではここでエラーになる
DROP USER
oss=# \d -- 8.0.xでは以下のようなオーナー無し状態が作れてしまう
       List of relations
 Schema | Name | Type  | Owner
--------+------+-------+-------
 public | foo  | table |
(1 row)
テーブルパーティションによる性能向上(Simon)

新しいconstraint_exclusion設定パラメータは、子テーブルに一致する行が存在しないことを制約が示している場合、子テーブルの検索を防ぎます。

これにより、テーブルパーティションの基本的な種類を実現できます。 子テーブルが別々のキー範囲を格納し、これを適切なCHECK制約で強制している場合、オブティマイザは、この制約により子テーブル内に一致することが内ことが保証されている時にその子テーブルへのアクセスを飛ばします。

以下に例を示します。継承関係にある work と work_old テーブルを親のworkから検索します。このとき constraint_exclusion を true にして(デフォルトはfalse)、stat != 'fin' という条件で検索すると、制約から該当行が無いことがわかる work_old は検索されなくなります。

oss=> CREATE TABLE work (id bigint, value text, stat text);
CREATE TABLE
oss=> CREATE TABLE work_old (CHECK (stat = 'fin')) INHERITS (work);
CREATE TABLE
oss=> INSERT INTO work SELECT i, 'xxxxx', 'accept' FROM generate_series (1, 10000) AS i;
INSERT 0 10000
oss=> INSERT INTO work_old SELECT i, 'xxxxx', 'fin' FROM generate_series (10001, 99999) AS i;
INSERT 0 89999
ss=> EXPLAIN SELECT * FROM work WHERE stat != 'fin'; -- 2テーブルを検索
                                  QUERY PLAN
-------------------------------------------------------------------------------
 Result  (cost=0.00..1944.99 rows=10001 width=26)
   ->  Append  (cost=0.00..1944.99 rows=10001 width=26)
         ->  Seq Scan on "work"  (cost=0.00..199.00 rows=10000 width=26)
               Filter: (stat <> 'fin'::text)
         ->  Seq Scan on work_old "work"  (cost=0.00..1745.99 rows=1 width=23)
               Filter: (stat <> 'fin'::text)
(6 rows)

oss=> SET constraint_exclusion TO true;
SET
oss=> EXPLAIN SELECT * FROM work WHERE stat != 'fin'; -- workのみを検索
                               QUERY PLAN
-------------------------------------------------------------------------
 Result  (cost=0.00..199.00 rows=10000 width=26)
   ->  Append  (cost=0.00..199.00 rows=10000 width=26)
         ->  Seq Scan on "work"  (cost=0.00..199.00 rows=10000 width=26)
               Filter: (stat <> 'fin'::text)
(4 rows)

バージョン8.1への移行

全ての以前のリリースからデータの移行を行うためには、pg_dumpを使用したダンプ、リストアが必要です。

8.0リリースでは、8.1でintervalに対するto_char()を削除するとアナウンスしましたが、より優れたAPIの提案がありませんでしたので、to_char(interval)は強化され、サーバに残りました。

以下の非互換性に注意してください。

その他の変更点

PostgreSQL8.1と以前のメジャーリリースとの間でなされた、その他の変更点について詳細を以下に示します。

性能向上

サーバの変更

問い合わせの変更

オブジェクト操作の変更

ユーティリティコマンドの変更

データ型および関数の変更

符号化方式およびロケールの変更

サーバサイド言語の一般的な変更

PL/PgSQLサーバサイド言語の変更

PL/Perlサーバサイド言語の変更

psqlの変更

pg_dumpの変更

E.1.3.13. libpqの変更

E.1.3.14. ソースコードの変更

E.1.3.15. Contribの変更


Copyright © 2005- SRA OSS, Inc. Japan All rights reserved.