ぱと隊長日誌

ブログ運用もエンジニアとしての生き方も模索中

PostgreSQLのデータベースクラスタ及びテーブルスペースの関係

はじめに

PostgreSQLの「データベースクラスタ」及び「テーブルスペース(テーブル空間)」の関係を説明します。

前提

このエントリではPostgreSQL 9.6のドキュメントをベースに解説します。

データベースクラスタ

PostgreSQLにおける「データベースクラスタ」とは1つのサーバインスタンスで管理するデータベースの集合体のことです。

ファイルシステムの観点からデータベースクラスタを見ると、『すべてのデータが格納される1つのディレクトリ』です。以下の記事の<図4:PostgreSQLファイル構成>がイメージしやすいです。
PostgreSQLアーキテクチャと性能の勘所

データベースクラスタ作成直後には3つのデータベース(posgres, template0, template1)が含まれています。

テーブルスペース(テーブル空間)

テーブルスペースはデータベースオブジェクト(データベース、テーブル、インデックス、シーケンス)の格納領域です。テーブルスペースを日本語版PostgreSQLマニュアルでは「テーブル空間」と表記しています。

デフォルトで用いられる格納領域のことを「デフォルトテーブルスペース」と呼びます。デフォルトテーブルスペースにはデータベースオブジェクトだけでなく、PostgreSQLの管理情報等(例えばトランザクションログ)も格納されます。

PostgreSQLのドキュメントではテーブルスペースを利用するメリットとして2つ挙げています。

(1)ディスクレイアウトの自由度が上がる
クラスタを作成したパーティションもしくはボリュームの容量が不足し、拡張を行うことができない場合でも、別パーティションにテーブルスペースを作ることでデータベースオブジェクトの増大に対応できます。

(2)データベースオブジェクトの特性に合わせて格納できる
頻繁にアクセスのあるインデックスを高速なSSDに格納したり、逆にアクセス頻度の低いテーブルを低速・低価格なハードディスクに格納することができます。

データベースクラスタとテーブルスペースの関係

先述の通り、データベースクラスタは『すべてのデータが格納される1つのディレクトリ』です。ですが、テーブルスペースはクラスタを作成したパーティション外にも作成できるとあります。一見矛盾しているこれらの要件ですが、PostgreSQLのドキュメントにヒントがあります。

ユーザが定義したテーブル空間はそれぞれ、PGDATA/pg_tblspcディレクトリ内に物理的なテーブル空間ディレクトリ(つまりそのテーブル空間のCREATE TABLESPACEコマンドで指定された場所)を指し示す、シンボリックリンクを持ちます。

65.1. データベースファイルのレイアウト

"PGDATA"は環境変数で、データベースクラスタディレクトリパスを示します。つまり、テーブルスペースのシンボリックリンクをデータベースクラスタ内に保持することで、『すべてのデータが格納される1つのディレクトリ』を実現しています。

なお、データベースクラスタ初期化時に2つのテーブルスペースが作成されます。

名称 パス 用途
pg_global PGDATA/global 共有システムカタログ用
pg_default PGDATA/base データベースのデフォルトスペース

これらはシンボリックリンクを介することなく、データベースクラスタ内のフォルダに紐付きます。

実例

テーブルスペースを作成・削除することでPGDATA/pg_tblspcディレクトリにシンボリックリンクが作成・削除されることの例を示します。理解を妨げない範囲で省略しています。

$ pg_ctl start -D /usr/local/pgsql/data/
$ ls -l /usr/local/pgsql/data/pg_tblspc
合計 0
$ ls -l /usr/local/
drwxr-xr-x. 7 postgres root 68 124 07:57 pgsql
drwxr-xr-x. 2 postgres root 6 39 22:18 pgsql_dbs
$ psql mydb
mydb=# CREATE TABLESPACE dbspace LOCATION '/usr/local/pgsql_dbs';
CREATE TABLESPACE
$ ls -l /usr/local/pgsql/data/pg_tblspc
合計 0
lrwxrwxrwx. 1 postgres postgres 20 39 22:24 16425 -> /usr/local/pgsql_dbs
mydb=# DROP TABLESPACE dbspace;
DROP TABLESPACE
$ ls -l /usr/local/pgsql/data/pg_tblspc
合計 0