パラレルクエリ

レプリケーションを設定することで検索を負荷分散させることができると説明したが、検索自体は1台のサーバで処理される。したがってデータが大量にある場合などでは、クエリをいずれかのノードに振り分けたとしてもあまり効果がない可能性がある。

そこで、pgpool-IIではもう1つの負荷分散方法を提供している。それはパラレルクエリと呼ばれる手法である。パラレルクエリとはルールに従ってデータを複数台に配置させ、分散されたデータを並列に検索する仕組みである。大容量のデータを細かく複数サーバへ分散させることにより、

  • 並列にデータを検索させることができる
  • 各サーバのデータ量が減るのでメモリキャッシュにヒットしやすくなる

という利点がある。データの分散ルールはユーザが自由に定義することができるので、会員番号、日付、住所などといったデータを分散キーに設定することが可能である。

それでは、今度はパラレルクエリを設定する。パラレルクエリを有効にするために、pgpool.confに以下の項目を追加する。なお、ここでの例では、PostgreSQLサーバがlocalhostの5432ポートと5433ポートで動いているものとする。

pgpool.conf

# レプリケーションの設定を無効
replication_mode = false

# パラレルクエリの設定を有効
parallel_mode = true

# localhost の5432ポートで動作しているサーバの設定
backend_hostname0 = 'localhost'
backend_port0 = 5432
backend_weight0 = 1

# localhost の5433ポートで動作しているサーバの設定
backend_hostname1 = 'localhost'
backend_port1 = 5433
backend_weight1 = 1

# 分散ルールを登録するサーバの設定
system_db_hostname = 'localhost'
system_db_port = 5432
system_db_dbname = 'pgpool'
system_db_schema = 'pgpool_catalog'
system_db_user = 'pgpool'
system_db_password = ''

pgpool-IIでは、分散ルールを登録するデータベースを「SystemDB」と呼ぶ。system_db_*パラメータはSystemDBへの接続を設定する。SystemDB で使うテーブルなどは/usr/local/pgpool/share/system_db.sqlに定義してあるので、このファイルを使ってテーブルを作成する。

SystemDBにはdblinkと呼ばれるPostgreSQLのcontribモジュールが必要なので、こちらもあわせてインストールする。

% createdb pgpool
% psql -f /usr/local/pgpool/share/system_db.sql pgpool
% psql -f /usr/local/pgsql/share/contrib/dblink.sql pgpool

次に分散ルールを登録する。分散ルールはPostgreSQLの関数を使って定義する。ここではIDと名前を持つmeiboテーブルを作成し、IDが偶数か奇数かで振り分けるように設定する。

分散ルールの定義

CREATE OR REPLACE FUNCTION pgpool_catalog.dist_rule (val INTEGER)
RETURNS INTEGER AS
$$ SELECT $1 % 2 $$
LANGUAGE SQL;

分散ルールの登録

INSERT INTO pgpool_catalog.dist_def VALUES (
  'parallel', 'public', 'meibo', 'id', ARRAY['id', 'name'],
  ARRAY['integer','text'], 'pgpool_catalog.dist_rule'
);

最初の関数定義が分散ルールを記述したSQL関数である。IDが偶数の場合はbackend0に、奇数の場合はbackend1にデータを登録する。次のINSERT文で「meiboテーブルのIDをdist_rule関数を使って振り分ける」というルールを登録している。

分散ルールの定義が完了したところで、pgpool-IIを起動する。現在のpgpool-IIの仕様では分散ルールを起動時のみ読み込むので、ルールの追加や再定義後にpgpool-IIを再起動する必要がある。

% pgpool -n &
% createdb -p 9999 parallel
% psql -f /usr/local/pgsql/
% psql -p 9999 parallel
CREATE TABLE meibo(id INTEGER, name TEXT);

次にデータを登録する。

データの追加

INSERT INTO meibo VALUES(0, '菊名');
INSERT INTO meibo VALUES(1, '白楽');
INSERT INTO meibo VALUES(2, '綱島');
INSERT INTO meibo VALUES(3, '日吉');

実際に分散されたか、各ノードに直接問い合わせてみると確認できる。

確認

% for p in 5432 5433; do
for> echo port:$p
for> psql -p $p -c 'SELECT * FROM meibo' parallel
for> done
port:5432
 id | name
----+------
  0 | 菊名
  2 | 綱島
(2 rows)
port:5433
 id | name
----+------
  1 | 白楽
  3 | 日吉
(2 rows)

分散されたデータをpgpool-IIを経由することで、すべてのデータをまとめる。 ソート処理も正しく動作する。

parallel=# select * from meibo order by id;
 id | name
----+------
  0 | 菊名
  1 | 白楽
  2 | 綱島
  3 | 日吉
(4 rows)

パラレルクエリにはいくつか制限事項が存在するので、パラレルクエリを試す際にはhttp://pgpool.sraoss.jp/index.php?pgpool-II%2Frestrictionを参照されたい。