PostgreSQL Advent Calendar 2012(全部俺)のDay 25です。
Advent Calendar最終日の今回は、少し大物としてPostgreSQLのMPPミドルウェア「Stado」の導入方法を紹介します。
Stado: The Open Source MPP Solution
https://launchpad.net/stado
皆さんは「MPP」という言葉を聞いたことがあるでしょうか。
コンピュータの世界で「MPP」と言えば「Massive Parallel Processing」、日本語で言うところの「超並列処理」のことを指します。
Massively parallel (computing) - Wikipedia, the free encyclopedia
http://en.wikipedia.org/wiki/Massive_parallel_processing
データベースの世界で「MPP」と言うと、通常は「シェアードナッシング・アーキテクチャ」のスケーラブルな並列処理用のコンピュータアーキテクチャのことを指します。ベンダ製品で言うと、Teradata、Netezza、Greenplumなどが有名どころでしょう。
MPPは昔からデータウェアハウス(DWH)と呼ばれる領域で採用されてきたことからも分かる通り、特に大規模なデータの分析や集計処理に威力を発揮します。
(実は、筆者は新入社員の頃、PostgreSQLを使ったオープンソースのMPPの研究開発プロジェクトに参加していたこともあり、MPPテクノロジーにはちょっと思い入れがあったりします。ちなみに、学生の頃には今で言うHadoopのような分散処理の研究をしていました。)
そのMPPのアーキテクチャをPostgreSQLと組み合わせて実現するためのオープンソースのミドルウェアが「Stado」です。
Stado: The Open Source MPP Solution
https://launchpad.net/stado
Stadoは、複数のPostgreSQLサーバを束ねて、あたかも単一のデータベースサーバであるかのように見せることができるミドルウェアです。
Stadoは、前々回のエントリで紹介したパーティショニングのうち、「ハッシュパーティショニング」の機能を提供します。Stadoを使うことによって、大容量のデータに対して並列処理をすることができ、単体のPostgreSQLと比べて実行時間を大幅に短縮することができます。
Stadoの紹介をしているとこれもまた長くなりますので、Stadoの概要については上記の資料をご参照ください。
今回は、このStadoを実際に導入する手順を説明します。
とは言っても、誰もが複数台のサーバを用意できるわけでもないでしょうから、今回は1台のサーバにマルチコアCPUと複数のハードディスクを積んで、一台のサーバで並列処理をする環境を構築する方法を解説します。
以下のように、ディスクを4本積んでいるサーバで並列処理をさせることを想定してStadoの導入を行ってみます。
Stadoの大まかな導入手順は以下の通りです。
今回Stadoを導入した環境は以下の通りです。
今回、PostgreSQLは9.2を、JDKはOpenJDKの1.6.0を使っています。
まずは、Stadoのソースコードを取得します。
通常は、分散ソースコード管理システムであるBazaarを使って以下から取得します。
https://code.launchpad.net/~sgdg/stado/stado
http://www.uptime.jp/go/stado
上記のURLから stado-20121223.tar.gz と install.sh スクリプトを取得します。
install.shスクリプトは、root権限で実行すると、OSアカウントのstadoユーザとstadoグループを作成し、必要なファイルを/usr/local/stadoにインストールします。
Stadoのインストールが終わったら、まずはPostgreSQLの設定を行います。
・基本設定
postgresql.confの設定を変更した項目は以下の通りです。
・テーブルスペースの作成
PostgreSQLサーバを起動したら、デフォルトのデータベースクラスタ /var/lib/pgsql/9.2/data 以外にテーブルスペースを作成します。
これらのテーブルスペースは、データベースクラスタとは別のディスク上に配置し、それによってI/O処理を分散させる目的で使用します。
ここでは、/disk/disk2, /disk/disk3, /disk/disk4 に、合計3本のディスクをマウントしているものとして、それらのディスクにそれぞれ tblspc2, tblspc3, tblspc4 というテーブルスペースを作成する設定を行います。
まず、テーブルスペースとして使用するディレクトリを作成し、postgresユーザ/postgresグループを所有者として権限を設定します。
・データベースユーザの作成
Stadoから接続するためのデータベースユーザを作成します。
このユーザは「Stado→PostgreSQL」の間で接続する際のデータベースユーザになります(ユーザからは直接は見えないユーザです)。ここでは「stado」という名前でデータベースユーザを作成します。
・Stadoの設定ファイル
/usr/local/stado/config にある stado_agent.config は以下を変更します。
同じディレクトリにある stado.config は、特に変更する項目はありません。ノードが4台であること、すべて 127.0.0.1 として扱うこと、として各種のパラメータが設定されていることを確認してください。
ここまで設定ができたら、gs-createmdb.shコマンドを使ってStadoのメタデータベースを作成します。このメタデータベースでは、ノードの情報や、テーブルのパーティション情報などを管理するものです。
この時、同時にStadoの管理者ユーザの情報も(メタデータベース内に)作成されます。ここでは、Stadoの管理者ユーザを「stadoadm」として作成しています。
メタデータベースの作成が終わったら、コーディネータプロセスを起動します。コーディネータプロセスの起動には gs-server.sh スクリプトを使います。
コーディネータの起動ができたら、次にエージェントプロセスの起動を行います。
エージェントプロセスは gs-agent.sh スクリプトで行い、-nオプションでStadoクラスタ内におけるエージェントの番号を指定します。
エージェントプロセスが起動したら、ユーザデータベースを作成することができます。
gs-createdb.shコマンドを使って、ユーザデータベースを作成します(メタデータベースを作成するコマンド gs-createmdb.sh とは違うコマンドであることに注意してください。名前が似ていますが)
データベースの一覧を見ると、今回作成したユーザデータベースtestdbが4つのパーティションを持っていることが分かります。gs-createdb.shコマンドを使ってStado上で作成した "testdb" というデータベースは、実際には "__testdb__N1" から "__testdb__N4" というパーティションに分割されています。
ここで、これらパーティションのテーブルスペースを見ると、すべて同じデフォルトのテーブルスペースに配置されていることが分かります。
まずは、gs-dbstop.sh コマンドを使って一旦データベースを停止させます。(内部的にStadoのコーディネータプロセスからPostgreSQLインスタンスへの切断を終了します)
ここまで終われば、Stadoのセットアップは完了です。Stadoのコーディネータプロセスにpsqlコマンドを使って通常のPostgreSQLと同じように接続することができます。(ポート番号はstado.confgで指定したポート番号、ユーザはメタデータベース作成時に指定したユーザになります)
それでは、実際にユーザデータベース testdb の中にテーブルを作ってみます。
パーティションに分割させずにすべてのノードに持たせるテーブルはCREATE TABLE文に "REPLICATED" の修飾子を付加します。
以下の例では、ordersテーブルとlineitemテーブルはレプリケーションテーブルとして全4ノードに同じものを配置、orders2テーブルとlineitem2テーブルはパーティションテーブルとして、それぞれo_orderkeyカラムとl_orderkeyカラムをパーティションキーとしてハッシュ分割して4分割されていることが分かります。
以下は、COPYコマンドを含むスクリプトを実行してデータをロードしている様子です。データロード実行後にテーブルサイズが大きくなっていることが分かります。
データをロードしたテーブルには、psqlコマンドを使って通常のPostgreSQLと同じようにクエリを実行することができます。
今回は、PostgreSQLを使ってMPPを実現するミドルウェア「Stado」について、その導入方法をご紹介してきました。(かなり駆け足になってしまいましたが)
BigDataやデータ分析の重要性が語られる時代になってきました。巷ではNoSQLなどの「新しいテクノロジー」が耳目を集めていますが、エンジニアの持っているスキルや業務データとの親和性を考えると、RDBMSが活躍できる余地はまだまだあるように(個人的には)感じています。
興味を持たれましたら、ぜひ試してみていただければと思います。
では、Happy Holidays!
Stado - The Open Source MPP Solution | StormDB
http://www.stormdb.com/community/stado
Stadoマニュアル 日本語(一部)対訳版
http://www.uptime.jp/go/stado/
PostgreSQL並列分散ミドルウェア「Stado」の紹介と検証報告
http://www.uptime.jp/ja/resources/techdocs/2012/07/stado/
Advent Calendar最終日の今回は、少し大物としてPostgreSQLのMPPミドルウェア「Stado」の導入方法を紹介します。
Stado: The Open Source MPP Solution
https://launchpad.net/stado
■「MPP」とは何か
皆さんは「MPP」という言葉を聞いたことがあるでしょうか。
コンピュータの世界で「MPP」と言えば「Massive Parallel Processing」、日本語で言うところの「超並列処理」のことを指します。
Massively parallel (computing) - Wikipedia, the free encyclopedia
http://en.wikipedia.org/wiki/Massive_parallel_processing
データベースの世界で「MPP」と言うと、通常は「シェアードナッシング・アーキテクチャ」のスケーラブルな並列処理用のコンピュータアーキテクチャのことを指します。ベンダ製品で言うと、Teradata、Netezza、Greenplumなどが有名どころでしょう。
MPPは昔からデータウェアハウス(DWH)と呼ばれる領域で採用されてきたことからも分かる通り、特に大規模なデータの分析や集計処理に威力を発揮します。
(実は、筆者は新入社員の頃、PostgreSQLを使ったオープンソースのMPPの研究開発プロジェクトに参加していたこともあり、MPPテクノロジーにはちょっと思い入れがあったりします。ちなみに、学生の頃には今で言うHadoopのような分散処理の研究をしていました。)
■PostgreSQL用MPPミドルウェア「Stado」
そのMPPのアーキテクチャをPostgreSQLと組み合わせて実現するためのオープンソースのミドルウェアが「Stado」です。
Stado: The Open Source MPP Solution
https://launchpad.net/stado
Stadoは、複数のPostgreSQLサーバを束ねて、あたかも単一のデータベースサーバであるかのように見せることができるミドルウェアです。
Stadoは、前々回のエントリで紹介したパーティショニングのうち、「ハッシュパーティショニング」の機能を提供します。Stadoを使うことによって、大容量のデータに対して並列処理をすることができ、単体のPostgreSQLと比べて実行時間を大幅に短縮することができます。
Stadoの紹介をしているとこれもまた長くなりますので、Stadoの概要については上記の資料をご参照ください。
今回は、このStadoを実際に導入する手順を説明します。
とは言っても、誰もが複数台のサーバを用意できるわけでもないでしょうから、今回は1台のサーバにマルチコアCPUと複数のハードディスクを積んで、一台のサーバで並列処理をする環境を構築する方法を解説します。
以下のように、ディスクを4本積んでいるサーバで並列処理をさせることを想定してStadoの導入を行ってみます。
■導入手順
Stadoの大まかな導入手順は以下の通りです。
- Stadoのインストール
- PostgreSQLのセットアップ
- Stadoのセットアップ
- ユーザデータベースの作成
- テーブルスペースへのパーティションの移動
- テーブルの作成とデータのロード
■導入環境
今回Stadoを導入した環境は以下の通りです。
- NEC Express5800 GT110b
- Xeon Intel Xeon X3440 2.53GHz (1P4C)
- Unbeffered ECC 16GB
- Hitachi Deskstar 7K1000 HDS72101
- Red Hat Enterprise Linux 6.3 (x86_64)
今回、PostgreSQLは9.2を、JDKはOpenJDKの1.6.0を使っています。
PostgreSQLとOpenJDKのインストールは完了しているものとして、ここからはStadoの導入を進めていきます。
[snaga@devsv03 ~]$ rpm -qa | grep postgresql
postgresql92-9.2.2-1PGDG.rhel6.x86_64
postgresql92-devel-9.2.2-1PGDG.rhel6.x86_64
postgresql92-server-9.2.2-1PGDG.rhel6.x86_64
postgresql92-contrib-9.2.2-1PGDG.rhel6.x86_64
postgresql92-libs-9.2.2-1PGDG.rhel6.x86_64
[snaga@devsv03 ~]$ rpm -qa | grep openjdk
java-1.6.0-openjdk-devel-1.6.0.0-1.45.1.11.1.el6.x86_64
java-1.6.0-openjdk-1.6.0.0-1.45.1.11.1.el6.x86_64
[snaga@devsv03 ~]$
■Stadoのインストール
まずは、Stadoのソースコードを取得します。
通常は、分散ソースコード管理システムであるBazaarを使って以下から取得します。
https://code.launchpad.net/~sgdg/stado/stado
とは言え、Bazzarをインストールしているユーザが多いとも思えないので、以下にソースコードとコンパイル済のjarファイルのパッケージを用意しました。
[snaga@devvm03 tmp]$ bzr branch lp:~sgdg/stado/stado
You have not informed bzr of your Launchpad ID, and you must do this to
write to Launchpad or access private data. See "bzr help launchpad-login".
Branched 55 revision(s).
[snaga@devvm03 tmp]$
http://www.uptime.jp/go/stado
上記のURLから stado-20121223.tar.gz と install.sh スクリプトを取得します。
install.shスクリプトは、root権限で実行すると、OSアカウントのstadoユーザとstadoグループを作成し、必要なファイルを/usr/local/stadoにインストールします。
[snaga@devsv03 stado]$ wget http://www.uptime.jp/downloads/stado/stado-20121223.tar.gz
(...snip...)
[snaga@devsv03 stado]$ wget http://www.uptime.jp/downloads/stado/install_stado.sh
(...snip...)
[snaga@devsv03 stado]$ ls
install_stado.sh stado-20121223.tar.gz
[snaga@devsv03 stado]$ tar zxf stado-20121223.tar.gz
[snaga@devsv03 stado]$ ls
install_stado.sh stado-20121223/ stado-20121223.tar.gz
[snaga@devsv03 stado]$ cd stado-20121223
[snaga@devsv03 stado-20121223]$ ls -F
bin/ build.xml docs/ lib/ README.TXT stado.config
build/ dist/ jars/ misc/ src/
[snaga@devsv03 stado-20121223]$ su
Password:
[root@devsv03 stado-20121223]# sh ../install_stado.sh
[root@devsv03 stado-20121223]# ls -l /usr/local/stado/
total 16
drwxr-xr-x. 2 stado stado 4096 Dec 23 18:06 bin/
drwxr-xr-x. 2 stado stado 4096 Dec 23 18:06 config/
drwxr-xr-x. 2 stado stado 4096 Dec 23 18:06 lib/
drwxrwxr-x. 2 stado stado 4096 Dec 23 18:06 log/
[root@devsv03 stado-20121223]#
■PostgreSQLのセットアップ
Stadoのインストールが終わったら、まずはPostgreSQLの設定を行います。
・基本設定
postgresql.confの設定を変更した項目は以下の通りです。
PostgreSQLの設定を行ったら、PostgreSQLサーバを起動します。
listen_addresses = '*'
max_connections = 100
shared_buffers = 2GB
work_mem = 2GB
maintenance_work_mem = 2GB
wal_buffers = 32MB
checkpoint_segments = 128
checkpoint_timeout = 60min
log_filename = 'postgresql-%Y%m%d.log'
log_min_duration_statement = 0
log_checkpoints = on
log_connections = on
log_disconnections = on
log_line_prefix = '[%t] %p: '
log_temp_files = 0
autovacuum = off
・テーブルスペースの作成
PostgreSQLサーバを起動したら、デフォルトのデータベースクラスタ /var/lib/pgsql/9.2/data 以外にテーブルスペースを作成します。
これらのテーブルスペースは、データベースクラスタとは別のディスク上に配置し、それによってI/O処理を分散させる目的で使用します。
ここでは、/disk/disk2, /disk/disk3, /disk/disk4 に、合計3本のディスクをマウントしているものとして、それらのディスクにそれぞれ tblspc2, tblspc3, tblspc4 というテーブルスペースを作成する設定を行います。
まず、テーブルスペースとして使用するディレクトリを作成し、postgresユーザ/postgresグループを所有者として権限を設定します。
次に、作成したディレクトリをテーブルスペースとしてPostgreSQL上で登録します。
[root@devsv03 pgsql]# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda3 936146792 739057756 148768328 84% /
/dev/sda1 101086 12010 83857 13% /boot
tmpfs 8213720 0 8213720 0% /dev/shm
/dev/sdb1 961432072 135545524 777048548 15% /disk/disk2
/dev/sdc1 961432072 53769008 858825064 6% /disk/disk3
/dev/sdd1 961432072 134776980 777817092 15% /disk/disk4
[root@devsv03 pgsql]#
[root@devsv03 pgsql]# mkdir /disk/disk2/pgsql
[root@devsv03 pgsql]# mkdir /disk/disk3/pgsql
[root@devsv03 pgsql]# mkdir /disk/disk4/pgsql
[root@devsv03 pgsql]# chown postgres:postgres /disk/disk4/pgsql /disk/disk3/pgsql /disk/disk2/pgsql
データベースクラスタ内の pg_tblspc ディレクトリの中身を確認して、テーブルスペースが作成されたことを確認します。
postgres=# select * from pg_tablespace;
spcname | spcowner | spcacl | spcoptions
------------+----------+--------+------------
pg_default | 10 | |
pg_global | 10 | |
(2 rows)
postgres=# create tablespace tblspc2 location '/disk/disk2/pgsql';
CREATE TABLESPACE
postgres=# create tablespace tblspc3 location '/disk/disk3/pgsql';
CREATE TABLESPACE
postgres=# create tablespace tblspc4 location '/disk/disk4/pgsql';
CREATE TABLESPACE
postgres=# select * from pg_tablespace;
spcname | spcowner | spcacl | spcoptions
------------+----------+--------+------------
pg_default | 10 | |
pg_global | 10 | |
tblspc2 | 10 | |
tblspc3 | 10 | |
tblspc4 | 10 | |
(5 rows)
postgres=#
これでテーブルスペースの作成は完了です。
[root@devsv03 pgsql]# ls -l /var/lib/pgsql/9.2/data/pg_tblspc
total 0
lrwxrwxrwx. 1 postgres postgres 17 Dec 23 18:38 16384 -> /disk/disk2/pgsql
lrwxrwxrwx. 1 postgres postgres 17 Dec 23 18:38 16385 -> /disk/disk3/pgsql
lrwxrwxrwx. 1 postgres postgres 17 Dec 23 18:38 16386 -> /disk/disk4/pgsql
[root@devsv03 pgsql]#
・データベースユーザの作成
Stadoから接続するためのデータベースユーザを作成します。
このユーザは「Stado→PostgreSQL」の間で接続する際のデータベースユーザになります(ユーザからは直接は見えないユーザです)。ここでは「stado」という名前でデータベースユーザを作成します。
ここまででPostgreSQLのセットアップは完了です。
[stado@devsv03 ~]$ createuser -d -E -U postgres -P stado
Enter password for new role:
Enter it again:
[stado@devsv03 ~]$ psql -h localhost -U stado postgres
psql (9.2.2)
Type "help" for help.
postgres=> \q
[stado@devsv03 ~]$
■Stadoのセットアップ
・Stadoの設定ファイル
/usr/local/stado/config にある stado_agent.config は以下を変更します。
これは「エージェントノードから見たコーディネータノードのホスト名/IPアドレス」ですが、今回は一台のサーバの中でエージェントもコーディネータも動作させるため、上記のような設定となります。
xdb.coordinator.host=127.0.0.1
同じディレクトリにある stado.config は、特に変更する項目はありません。ノードが4台であること、すべて 127.0.0.1 として扱うこと、として各種のパラメータが設定されていることを確認してください。
・メタデータベースとStado管理者ユーザの作成
xdb.port=6453
xdb.maxconnections=10
xdb.default.dbusername=stado
xdb.default.dbpassword=stado
xdb.default.dbport=5432
xdb.default.threads.pool.initsize=2
xdb.default.threads.pool.maxsize=10
xdb.metadata.database=XDBSYS
xdb.metadata.dbhost=127.0.0.1
xdb.nodecount=4
xdb.node.1.dbhost=127.0.0.1
xdb.node.2.dbhost=127.0.0.1
xdb.node.3.dbhost=127.0.0.1
xdb.node.4.dbhost=127.0.0.1
xdb.coordinator.node=1
ここまで設定ができたら、gs-createmdb.shコマンドを使ってStadoのメタデータベースを作成します。このメタデータベースでは、ノードの情報や、テーブルのパーティション情報などを管理するものです。
この時、同時にStadoの管理者ユーザの情報も(メタデータベース内に)作成されます。ここでは、Stadoの管理者ユーザを「stadoadm」として作成しています。
いろいろなメッセージが出て、最後に「User [USER] is created」と出たらメタデータベースの作成は成功です。
[stado@devsv03 ~]$ cd /usr/local/stado/bin
[stado@devsv03 bin]$ ./gs-createmddb.sh -u stadoadm -p password
Executed Statement: create table xsystablespaces ( tablespaceid serial, tablespacename varchar(255) not null, ownerid int not null, primary key(tablespaceid))
Executed Statement: create unique index idx_xsystablespaces_1 on xsystablespaces (tablespacename)
(...snip...)
Executed Statement: create unique index idx_xsyschecks_1 on xsyschecks (constid, seqno)
Executed Statement: alter table xsyschecks add foreign key (constid) references xsysconstraints (constid)
User stadoadm is created
[stado@devsv03 bin]$
■コーディネータプロセスの起動
メタデータベースの作成が終わったら、コーディネータプロセスを起動します。コーディネータプロセスの起動には gs-server.sh スクリプトを使います。
Javaのプロセスが起動したら成功です。
[stado@devsv03 bin]$ ./gs-server.sh
Starting....
[stado@devsv03 bin]$ ps -aef | grep stado
root 29892 29721 0 18:59 pts/3 00:00:00 su - stado
stado 29893 29892 0 18:59 pts/3 00:00:00 -bash
stado 30045 1 2 19:06 pts/3 00:00:00 java -classpath ../lib/stado.jar:../lib/log4j.jar:../lib/postgresql.jar: -Xms512M -Xmx512M -Xss256K -Dconfig.file.path=../config/stado.config org.postgresql.stado.util.XdbServer
postgres 30064 29604 0 19:06 ? 00:00:00 postgres: stado XDBSYS 127.0.0.1(48401) idle
stado 30099 29893 1 19:06 pts/3 00:00:00 ps -aef
stado 30100 29893 0 19:06 pts/3 00:00:00 grep stado
[stado@devsv03 bin]$
■エージェントプロセスの起動
コーディネータの起動ができたら、次にエージェントプロセスの起動を行います。
エージェントプロセスは gs-agent.sh スクリプトで行い、-nオプションでStadoクラスタ内におけるエージェントの番号を指定します。
[stado@devsv03 bin]$ ./gs-agent.sh -n 4
Starting....
[stado@devsv03 bin]$ ps -aef | grep stado
root 29892 29721 0 18:59 pts/3 00:00:00 su - stado
stado 29893 29892 0 18:59 pts/3 00:00:00 -bash
stado 30045 1 0 19:06 pts/3 00:00:00 java -classpath ../lib/stado.jar:../lib/log4j.jar:../lib/postgresql.jar: -Xms512M -Xmx512M -Xss256K -Dconfig.file.path=../config/stado.config org.postgresql.stado.util.XdbServer
postgres 30064 29604 0 19:06 ? 00:00:00 postgres: stado XDBSYS 127.0.0.1(48401) idle
stado 30112 1 4 19:07 pts/3 00:00:00 java -classpath ../lib/stado.jar:../lib/log4j.jar:../lib/postgresql.jar: -Xms256M -Xmx256M -Dconfig.file.path=../config/stado_agent.config org.postgresql.stado.util.XdbAgent -n 4
stado 30135 29893 1 19:07 pts/3 00:00:00 ps -aef
stado 30136 29893 0 19:07 pts/3 00:00:00 grep stado
[stado@devsv03 bin]$
■ユーザーデータベースの作成
エージェントプロセスが起動したら、ユーザデータベースを作成することができます。
gs-createdb.shコマンドを使って、ユーザデータベースを作成します(メタデータベースを作成するコマンド gs-createmdb.sh とは違うコマンドであることに注意してください。名前が似ていますが)
ユーザデータベースを作成したら、gs-cmdline.shコマンドでデータベースの状態を確認します。
[stado@devsv03 bin]$ ./gs-createdb.sh -d testdb -u stadoadm -p password -n 1,2,3,4
OK
[stado@devsv03 bin]$
show databasesコマンドの結果を見ると、ここで作成したデータベースtestdbは、ステータスは利用開始されており、ノードは1から4に配置されていることが分かります。
[stado@devsv03 bin]$ ./gs-cmdline.sh -d testdb -u stadoadm -p password
Stado -> show databases;
+------------------------------+
| DATABASE | STATUS | NODES |
+------------------------------+
| testdb | Started | 1,2,3,4 |
+------------------------------+
1 row(s).
Stado ->
[stado@devsv03 bin]$
■パーティションのテーブルスペースへの移動
データベースの一覧を見ると、今回作成したユーザデータベースtestdbが4つのパーティションを持っていることが分かります。gs-createdb.shコマンドを使ってStado上で作成した "testdb" というデータベースは、実際には "__testdb__N1" から "__testdb__N4" というパーティションに分割されています。
ここで、これらパーティションのテーブルスペースを見ると、すべて同じデフォルトのテーブルスペースに配置されていることが分かります。
このままでは、すべてのパーティションが単一のディスク上に配置されてしまってクエリのI/O処理が分散されませんので、先ほど作成したテーブルスペースにこれらのデータベースパーティションを移動させます。
postgres=> SELECT datname,dattablespace,spcname
postgres-> FROM pg_database d LEFT OUTER JOIN pg_tablespace s
postgres-> ON d.dattablespace=s.oid;
datname | dattablespace | spcname
--------------+---------------+------------
template1 | 1663 | pg_default
template0 | 1663 | pg_default
postgres | 1663 | pg_default
XDBSYS | 1663 | pg_default
__testdb__N1 | 1663 | pg_default
__testdb__N2 | 1663 | pg_default
__testdb__N3 | 1663 | pg_default
__testdb__N4 | 1663 | pg_default
(8 rows)
postgres=>
まずは、gs-dbstop.sh コマンドを使って一旦データベースを停止させます。(内部的にStadoのコーディネータプロセスからPostgreSQLインスタンスへの切断を終了します)
データベースを停止したら、各パーティションをそれぞれのテーブルスペースに移動させます。
[stado@devsv03 bin]$ ./gs-dbstop.sh -u stadoadm -p password -d testdb
Database(s) testdb stopped.
[stado@devsv03 bin]$
テーブルスペースへの移動が終わったら、最後にgs-dbstart.shコマンドを使ってデータベースを再開させます。
[stado@devsv03 bin]$ psql -U postgres postgres
psql (9.2.2)
Type "help" for help.
postgres=# ALTER DATABASE "__testdb__N2" SET TABLESPACE tblspc2;
ALTER DATABASE
postgres=# ALTER DATABASE "__testdb__N3" SET TABLESPACE tblspc3;
ALTER DATABASE
postgres=# ALTER DATABASE "__testdb__N4" SET TABLESPACE tblspc4;
ALTER DATABASE
postgres=# SELECT datname,dattablespace,spcname
postgres-# FROM pg_database d LEFT OUTER JOIN pg_tablespace s
postgres-# ON d.dattablespace=s.oid;
datname | dattablespace | spcname
--------------+---------------+------------
template1 | 1663 | pg_default
template0 | 1663 | pg_default
postgres | 1663 | pg_default
XDBSYS | 1663 | pg_default
__testdb__N1 | 1663 | pg_default
__testdb__N2 | 16384 | tblspc2
__testdb__N3 | 16385 | tblspc3
__testdb__N4 | 16386 | tblspc4
(8 rows)
postgres=# \q
[stado@devsv03 bin]$ ./gs-dbstart.sh -u stadoadm -p password -d testdb
Database(s) testdb started.
[stado@devsv03 bin]$
■ユーザデータベースへの接続
ここまで終われば、Stadoのセットアップは完了です。Stadoのコーディネータプロセスにpsqlコマンドを使って通常のPostgreSQLと同じように接続することができます。(ポート番号はstado.confgで指定したポート番号、ユーザはメタデータベース作成時に指定したユーザになります)
[stado@devsv03 bin]$ psql -p 6453 -h localhost -U stadoadm testdb
Password for user stadoadm:
psql (9.2.2, server 9.0.1)
WARNING: psql version 9.2, server version 9.0.
Some psql features might not work.
Type "help" for help.
testdb=>
■テーブルの作成とデータのロード
それでは、実際にユーザデータベース testdb の中にテーブルを作ってみます。
パーティションに分割させずにすべてのノードに持たせるテーブルはCREATE TABLE文に "REPLICATED" の修飾子を付加します。
パーティション分割させるテーブルは、CREATE TABLE文でパーティションキーを指定して "PARTITIONING KEY ... ON ALL" の修飾子を付加します。
CREATE TABLE orders (
o_orderkey INTEGER,
o_custkey INTEGER,
o_orderstatus CHAR(1),
o_totalprice REAL,
o_orderDATE DATE,
o_orderpriority CHAR(15),
o_clerk CHAR(15),
o_shippriority INTEGER,
o_comment VARCHAR(79)
)
REPLICATED;
以下は、実際に CREATE TABLE 文を記述したスクリプトを実行してテーブルを作成している様子です。
CREATE TABLE orders2 (
o_orderkey INTEGER,
o_custkey INTEGER,
o_orderstatus CHAR(1),
o_totalprice REAL,
o_orderDATE DATE,
o_orderpriority CHAR(15),
o_clerk CHAR(15),
o_shippriority INTEGER,
o_comment VARCHAR(79)
)
PARTITIONING KEY o_orderkey ON ALL;
テーブルを作成した後、gs-cmdline.shコマンドを起動して show tables コマンドを実行すると、作成したテーブルがどのように配置されているかを確認することができます。
testdb=> \i create_tables.sql
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
testdb=> \d+
List of relations
Schema | Name | Type | Owner | Size | Description
--------+-----------+-------+-------+---------+-------------
public | lineitem | table | stado | 0 bytes |
public | lineitem2 | table | stado | 0 bytes |
public | orders | table | stado | 0 bytes |
public | orders2 | table | stado | 0 bytes |
(4 rows)
testdb=>
以下の例では、ordersテーブルとlineitemテーブルはレプリケーションテーブルとして全4ノードに同じものを配置、orders2テーブルとlineitem2テーブルはパーティションテーブルとして、それぞれo_orderkeyカラムとl_orderkeyカラムをパーティションキーとしてハッシュ分割して4分割されていることが分かります。
データのローディングにはCOPYコマンドを使うことができます。
[stado@devsv03 ~]$ cd /usr/local/stado/bin/
[stado@devsv03 bin]$ ./gs-cmdline.sh -u stadoadm -p password -d testdb
Stado -> show tables;
+-----------------------------------------------------+
| TABLE | TABLE_PARTITIONING_COLUMN | TABLE_NODES |
+-----------------------------------------------------+
| lineitem | | 1,2,3,4 |
| lineitem2 | l_orderkey | 1,2,3,4 |
| orders | | 1,2,3,4 |
| orders2 | o_orderkey | 1,2,3,4 |
+-----------------------------------------------------+
4 row(s).
Stado ->
以下は、COPYコマンドを含むスクリプトを実行してデータをロードしている様子です。データロード実行後にテーブルサイズが大きくなっていることが分かります。
testdb=> \i load_tables.sql
Timing is on.
Time: 162623.103 ms
Time: 64810.198 ms
Time: 763729.597 ms
Time: 320365.227 ms
testdb=> \d+
List of relations
Schema | Name | Type | Owner | Size | Description
--------+-----------+-------+-------+---------+-------------
public | lineitem | table | stado | 8326 MB |
public | lineitem2 | table | stado | 2081 MB |
public | orders | table | stado | 1979 MB |
public | orders2 | table | stado | 495 MB |
(4 rows)
testdb=>
■クエリの実行
データをロードしたテーブルには、psqlコマンドを使って通常のPostgreSQLと同じようにクエリを実行することができます。
testdb=> select count(*) from orders;
count(*)
----------
15000000
(1 row)
Time: 1870.665 ms
testdb=> select count(*) from orders2;
count(*)
----------
15000000
(1 row)
Time: 650.026 ms
testdb=>
■まとめ
今回は、PostgreSQLを使ってMPPを実現するミドルウェア「Stado」について、その導入方法をご紹介してきました。(かなり駆け足になってしまいましたが)
BigDataやデータ分析の重要性が語られる時代になってきました。巷ではNoSQLなどの「新しいテクノロジー」が耳目を集めていますが、エンジニアの持っているスキルや業務データとの親和性を考えると、RDBMSが活躍できる余地はまだまだあるように(個人的には)感じています。
興味を持たれましたら、ぜひ試してみていただければと思います。
では、Happy Holidays!
■参考資料
Stado - The Open Source MPP Solution | StormDB
http://www.stormdb.com/community/stado
Stadoマニュアル 日本語(一部)対訳版
http://www.uptime.jp/go/stado/
PostgreSQL並列分散ミドルウェア「Stado」の紹介と検証報告
http://www.uptime.jp/ja/resources/techdocs/2012/07/stado/