PostgreSQL

pg_shardによるPostgreSQLのシャーディング

More than 1 year has passed since last update.

MySQLにはシャーディング機能があるらしいですが、PostgreSQLには実装されていません。

しかし、今回紹介する追加モジュール「pg_shard」によってシャーディング機能を使用することができます。

pg_shard ver.1.2.3 https://github.com/citusdata/pg_shard

ただし、pg_shardは現在推奨されておらず、PostgreSQLをベースとしたcitus DBに開発を移したみたいです。


シャーディングとは

データを複数のノードに分散させることで、マシンリソース(CPU、I/O)を効率よく使うことができる仕組みです。

大規模なデータを取り扱う場合には重要になる機能です。

図:データが分散されるイメージ

pg_shard_分散のイメージ.PNG

pg_shardの場合、Masterノードと呼ばれるサーバが受け取ったクエリを良しなに振り分けを行い、振り分けられた処理をWorkerノードが処理する仕組みになっています。


前提条件

以下、構築した内容です。


  • CentOS 7.2

  • PostgreSQL 9.4.7

  • pg_shard 1.2.3

構成として、VMを3台使用しています。

pg_shardを使用したシャーディングを行う場合、最低でもDBは3台以上が必要になります。

pg_shard_構成図.PNG


構築手順


1. Workerノード作成

以下のWorkerノード構築の手順となります。

WorkerノードとなるPostgreSQLを2台を構築するため、最初にPostgreSQLをインストールします。方法は何でもOKで、yum使っても、直接RPMを使ってもソースからコンパイル等、好きなものを選んでください。

今回はyumを使ってPostgreSQLを構築します。


1-1. PostgreSQLのyumリポジトリ登録

以下の手順ではじめにPostgreSQLのyumリポジトリを登録します。

# wget https://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-2.noarch.rpm

# rpm -ivh pgdg-centos94-9.4-2.noarch.rpm

必要なときにだけ、リポジトリを有効にするため、以下のファイルの修正を行ってください。


/etc/yum.repos.d/pgdg-94-centos.repo

[pgdg94]

・・・
#enabled=1
enabled=0


1-2. PostgreSQLのインストール

pg_shardはmakeする必要があるため、postgresql94-serverに加えて、postgresql94-devel、postgresql94-contribが必要になります。

# yum --enablerepo=pgdg94 install postgresql94-server postgresql94-devel postgresql94-contrib


1-3. 環境設定

初期設定として以下を実施する。

# su - postgres

$ vi ~/.bashrc

--以下の内容を追記---
export PATH=/usr/pgsql-9.4/bin:$PATH
--------------------

$ vi ~/.bash_profile

--以下の内容を追記---
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
--------------------


1-4. DBの作成

初期設定が終わったら、以下のコマンドを実行し、PostgreSQLを構築します。

$ source ~/.bashrc

$ initdb --no-locale --encoding=utf-8
$ vi $PGDATA/postgresql.conf
$ vi $PGDATA/pg_hba.conf


$PGDATA/postgresql.conf

listen_addresses = '*'

shared_preload_libraries = 'pg_shard'


$PGDATA/pg_hba.conf

host    all       all      192.168.1.0/24     trust



1-5. pg_shardのインストール

PostgreSQLのリポジトリには7/31現在では最新版のRPMが提供されていなかったので、ソースコンパイルを実施します。

$ wget https://github.com/citusdata/pg_shard/archive/v1.2.3.tar.gz

$ tar -xvf v1.2.3.tar.gz
$ cd pg_shard-1.2.3
$ make
$ sudo -H PATH=/usr/pgsql-9.4/bin:$PATH make install


1-6. Workerノード構築完了

構築が完了したら、起動しておきます。

$ pg_ctl start

$ createdb testdb

※あとで動作確認するためにtestdbという名前でDBを作っています。


2. Masterノード作成

手順は「pg_shardのインストール」まではWorkerノードと同じです。

異なるのは、手順2-6以降のpg_shardの設定を行う箇所のみです。


2-1. PostgreSQLのyumリポジトリ登録

# wget https://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-2.noarch.rpm

# rpm -ivh pgdg-centos94-9.4-2.noarch.rpm


/etc/yum.repos.d/pgdg-94-centos.repo

[pgdg94]

・・・
#enabled=1
enabled=0


2-2. PostgreSQLのインストール

# yum --enablerepo=pgdg94 install postgresql94-server postgresql94-devel postgresql94-contrib


2-3. 環境設定

# su - postgres

$ vi ~/.bashrc

--以下の内容を追記---
export PATH=/usr/pgsql-9.4/bin:$PATH
--------------------

$ vi ~/.bash_profile

--以下の内容を追記---
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
--------------------


2-4. DBの作成

$ source ~/.bashrc

$ initdb --no-locale --encoding=utf-8
$ vi $PGDATA/postgresql.conf
$ vi $PGDATA/pg_hba.conf


$PGDATA/postgresql.conf

listen_addresses = '*'

shared_preload_libraries = 'pg_shard'


$PGDATA/pg_hba.conf

host    all       all      192.168.1.0/24     trust



2-5. pg_shardのインストール

$ wget https://github.com/citusdata/pg_shard/archive/v1.2.3.tar.gz

$ tar -xvf v1.2.3.tar.gz
$ cd pg_shard-1.2.3
$ make
$ sudo -H PATH=/usr/pgsql-9.4/bin:$PATH make install


2-6. pg_shardの設定ファイルを作成

Workerノードで起動しているPostgreSQLへの接続情報(接続先ホスト、ポート番号)を書きます。


$PGDATA/pg_worker_list.conf

192.168.1.2 5432

192.168.1.3 5432


2-7. Masterノード起動

Masterノードを作成したら、シャーディングを行うDBを作成します。

$ pg_ctl start

$ createdb testdb


2-8. pg_shardモジュールのDBへの読み込み

作成したtestdbにpg_shardを読み込みませます。

$psql testdb -U postgres -c 'CREATE EXTENSION pg_shard'

これで、pg_shardの独自関数等がtestdb内で使用することができます。


2-9. シャーディングの設定を行う


2-9-1. シャーディングの対象となるテーブルを作成する

$ psql testdb -U postgres -c 'CREATE TABLE shard_tbl (id int PRIMARY KEY,var varchar(30))'


2-9-2. シャーディングを行う対象のテーブルとキーをpg_shardの独自関数で指定する。

$ psql testdb -U postgres -c "SELECT master_create_distributed_table('shard_tbl', 'id')"


2-9-3. シャーディングの詳細(シャード数、レプリケーション数)を設定する。

$ psql testdb -U postgres -c "SELECT master_create_worker_shards('shard_tbl',2,1)"

項目名
概要

シャード数
データを分散する数

レプリケーション数
データを複製する数

今回はWorkerノードが2台あるので、2箇所に分散されテイク様子を確認したいのでシャード数に「2」、レプリケーション数に「1」を設定します。


2-10. Masterノード設定完了

これで準備は整いました。

あとはデータをINSERTして、挙動を確かめるだけの簡単なお仕事です。


3. 動作確認


3-1. 10件のデータをINSERTする

$ for i in `seq 0 9` ;do psql testdb -U postgres -c "INSERT INTO shard_tbl VALUES ($i,'XXXXXXXXX')"; done

色々試した結果、1行スクリプトでやることにしました。


3-2. 各ノードのデータをSELECTしてみる


  • Masterノード

ちゃんと入力したデータは書き込まれていますね。

testdb=# select * from shard_tbl;                                                                

id | var
----+-----------
0 | XXXXXXXXX
1 | XXXXXXXXX
3 | XXXXXXXXX
4 | XXXXXXXXX
5 | XXXXXXXXX
7 | XXXXXXXXX
8 | XXXXXXXXX
2 | XXXXXXXXX
6 | XXXXXXXXX
9 | XXXXXXXXX
(10 rows)


  • Workerノード1

3件だけ書き込まれているようです。

testdb=# select * from shard_tbl_10006 ;

id | var
----+-----------
2 | XXXXXXXXX
6 | XXXXXXXXX
9 | XXXXXXXXX
(3 rows)


  • Workerノード2

こちらは残りの7件が書き込まれていますね。

testdb=# select * from shard_tbl_10005 ;

id | var
----+-----------
0 | XXXXXXXXX
1 | XXXXXXXXX
3 | XXXXXXXXX
4 | XXXXXXXXX
5 | XXXXXXXXX
7 | XXXXXXXXX
8 | XXXXXXXXX
(7 rows)

なるほど、ちゃんとデータは分散されているようですね。


使ってみて気づいた点

結構実行できるクエリに制限がありそうです。

テストデータのINSERTを試しただけでも以下の制限に引っかかりました。


  • サブクエリの制限

$ psql testdb -U postgres -c "INSERT INTO shard_tbl SELECT generate_Series(1,10),(random()*10000)::int%10000"

ERROR: cannot perform distributed planning for the given query
DETAIL: Subqueries are not supported in distributed queries.


  • SQL関数による制限

$ for i in `seq 0 9` ;do psql testdb -U postgres -c "INSERT INTO shard_tbl VALUES ($i,random())"; done

ERROR: cannot plan sharded modification containing values which are not constants or constant expressions

これはFDWとか等による制約でしょうか。

他にもいくつか制約があるようで公式のマニュアルをご確認ください。