本チュートリアルでは簡単なPostgresForestの構築作業を通して、 PostgresForest を使うための事前準備、環境構築ツールの使用方法、仮想化 モジュールを使用したデータベースアクセスの手順の概要を説明します。
本チュートリアルは、以下の5つのステップから構成されます。
本チュートリアルは、以下の環境で動作確認をしています。
ここでは、PostgreSQLが /usr/local/pgsql815 に、j2sdkが /usr/java/j2sdk1.4.2_13 にインストールされているものとします。
これらの環境のデータベースサーバを二台用意し、二台構成のPostgresForest 環境を構築します。
まず、二台のDBサーバ上にユーザ 'forest' を作成、そのホームディレクトリ を /home/forest とし、以降の作業はこのユーザにて行います。
環境変数 JAVA_HOME と PGHOME を設定し、PGHOME/bin を PATH に設定します。:
JAVA_HOME=/usr/java/j2sdk1.4.2_13 PGHOME=/usr/local/pgsql815 PATH=${PGHOME}/bin:${JAVA_HOME}/bin:${PATH} export JAVA_HOME PGHOME PATH
インストール作業に入る前に、PostgresForestの配布パッケージ (PostgresForest-4.0.zip)をダウンロードし、forest ユーザのホームディ レクトリに配置しておきます。
PostgresForestダウンロードサイト http://www.nttdata.co.jp/services/postgresforest/
unzipコマンドを使って、PostgresForest配布パッケージをを解凍しすると、 ディレクトリ PostgresForest-4.0 が作成されます。二台のサーバでそれぞれ 解凍しておきます。:
[forest@db0:~]$ ls PostgresForest-4.0.zip [forest@db0:~]$ unzip PostgresForest-4.0.zip Archive: PostgresForest-4.0.zip creating: PostgresForest-4.0/ [...snip...] inflating: PostgresForest-4.0/examples/scripts/broken_servers.sh [forest@db0:~]$
[forest@db1 ~]$ ls PostgresForest-4.0.zip [forest@db1 ~]$ Archive: PostgresForest-4.0.zip creating: PostgresForest-4.0/ [...snip...] inflating: PostgresForest-4.0/examples/scripts/broken_servers.sh [forest@db1 ~]$
各インストーラの設定ファイル env.confを環境に合わせて設定します。 ここでは、以下の設定とします。:
[forest@db0:~]$ cd PostgresForest-4.0 [forest@db0:~/PostgresForest-4.0]$ ls bin/ build.sh* env.conf install.sh* MANIFEST setup.sh* src/ build/ common.conf examples/ lib/ README share/ [forest@db0:~/PostgresForest-4.0]$ vi env.conf
env.confの内容は以下のようになります。:
DESTDIR=/usr/local/forest40 JAVA_HOME=/usr/java/j2sdk1.4.2_13 PGHOME=/usr/local/pgsql815 PGUSER=forest PGPORT=5432 PGDATA=/home/forest/data
同様に、二台目のサーバでもenv.confを設定します。
続けて、env.confを設定したディレクトリでbuild.shを実行して、関連モジュー ルのビルドを行います。:
[forest@db0:~/PostgresForest-4.0]$ sh build.sh PostgreSQL version: 8.1 Applying lock-timeout support patch to pl/java. patching file src/C/pljava/Backend.c make[1]: Entering directory `/home/forest/PostgresForest-4.0/build/pljava-1.3.0/build/classes/pljava' javac -source 1.4 -target 1.4 -d . <java sources> [...snip...] gcc -DPOSTGRES81=1 -fpic -shared -Wl,-soname,libforest_recovery.so.0 forest_recovery.o -L/usr/local/pgsql815/lib -Wl,-rpath,/usr/local/pgsql815/lib -o libforest_recovery.so.0.0 rm -f libforest_recovery.so.0 ln -s libforest_recovery.so.0.0 libforest_recovery.so.0 rm -f libforest_recovery.so ln -s libforest_recovery.so.0.0 libforest_recovery.so [forest@db0:~/PostgresForest-4.0]$
同様に、もう一台のサーバでもbuild.shを実行してビルドを行います。
ビルドが完了したら、rootになり、install.shを実行してPostgresForestの関 連するファイルをインストールします。:
[forest@db0:~/PostgresForest-4.0]$ su Password: [root@db0 PostgresForest-4.0]# sh install.sh PostgreSQL version: 8.1 Creating /usr/local/forest40 /usr/local/forest40/bin /usr/local/forest40/lib /usr/local/forest40/share /usr/local/forest40/src done. =============================================== ====== All files installed successfully. ====== =============================================== [root@db0 PostgresForest-4.0]#
「All files installed successfully.」とメッセージが出力されたら、イン ストールは完了です。もう一台のサーバでも同様にinstall.shによってインス トールを行います。
一般ユーザになってforest_initdbを実行し、PostgresForestのデータベース クラスタのセットアップを行います。:
[forest@db0:~/PostgresForest-4.0]$ /usr/local/forest40/bin/forest_initdb The files belonging to this database system will be owned by user "forest". This user must also own the server process. [...snip...] ====================================================== ====== PostgresForest initialized successfully. ====== ====================================================== waiting for postmaster to shut down....LOG: received smart shutdown request LOG: shutting down LOG: database system is shut down done postmaster stopped [forest@db0:~/PostgresForest-4.0]$
forest_initdbコマンドでは、PostgreSQLの通常のinitdbコマンドの処理に加 えて、PostgresForestで必要とされる各種サポート関数のインストールや PostgresForest用テンプレートデータベースの作成などを行います。
forest_initdbの最後で「PostgresForest initialized successfully.」と表 示されたらセットアップは完了です。もう片方のノードでも同様のセットアッ プ作業を行います。
インストーラによって作成された各データベースノードに、外部から接続でき るようにネットワーク接続の設定を行います。
まず、PGDATA/postgresql.confの listen_address を以下のように設定します。:
listen_addresses = '*' port = 5432
これによって、起動されたpostmasterがソケットをlistenするようになります。
次に、データベースノードに外部から接続可能とする設定を行います。
PGDATA/pg_hba.confに、以下のように接続するサーバ(通常はAPサーバ)のIP アドレスあるいはネットワークを設定します。
以下の例は「192.168.0.0/24」ネットワークから接続を受け付ける場合の設定 になります。:
host all all 192.168.0.0/24 password
設定が終わったら、forest_ctlコマンドを使用して各データベースノード上で PostgreSQLインスタンス(postmaster)を起動します。:
[forest@db0:~/PostgresForest-4.0]$ /usr/local/forest40/bin/forest_ctl -D /home/forest/data -l /home/forest/data/forest.log start postmaster starting [forest@db0:~/PostgresForest-4.0]$
下記コマンドによって、各データベースノード上のPostgreSQLにアクセス可能 であることを確認します。:
[forest@db0:~/PostgresForest-4.0]$ /usr/local/pgsql815/bin/psql -h 192.168.1.101 -l forest_template List of databases Name | Owner | Encoding -----------------+--------+----------- forest_template | forest | UTF8 postgres | forest | SQL_ASCII template0 | forest | SQL_ASCII template1 | forest | SQL_ASCII (4 rows) [forest@db0:~/PostgresForest-4.0]$ /usr/local/pgsql815/bin/psql -h 182.168.1.102 -l forest_template List of databases Name | Owner | Encoding -----------------+--------+----------- forest_template | forest | UTF8 postgres | forest | SQL_ASCII template0 | forest | SQL_ASCII template1 | forest | SQL_ASCII (4 rows) [forest@db0:~/PostgresForest-4.0]$
各インスタンスに外部から接続できることを確認したら、各PostgreSQLにおい てALTER USERコマンドを実行し、ユーザforestのパスワードを設定します。こ こではパスワードを「forest」としています(この設定は全インスタンスで実 行する必要があります)。:
forest_template=# ALTER USER forest PASSWORD 'forest'; ALTER ROLE forest_template=#
インストールしたPostgresForestの環境構築ツールを用いて、グローバルシス テムカタログ(GSC)を作成します(環境構築ツールの詳細については、「環 境構築ツールマニュアル」を参照してください)。:
[forest@db0:~]$ /usr/local/forest40/bin/forestadm -h 192.168.1.101 -p 5432 -g gsc -U forest -W forest -i Welcome to PostgresForest Command Line Tool. Connecting to Database GSC = 192.168.1.101:5432/gsc cui.message.gsc.make [forest@db0:~]$
作成したGSCに接続し、show gscコマンドを用いてGSCが作成されていることを確認します。:
[forest@db0:~]$ /usr/local/forest40/bin/forestadm -h 192.168.1.101 -p 5432 -g gsc -U forest -W forest Welcome to PostgresForest Command Line Tool. Connecting to Database GSC = 192.168.1.101:5432/gsc [gsc]$ show gsc; グローバルシステムカタログ一覧 DBNAME | HOST | PORT | SERVERID ------------------------------------------ gsc | 192.168.1.101 | 5432 | 0 [gsc]$
create instanceコマンドを使って、もう一台のインスタンスをGSCに登録、 show instanceコマンドを使って結果を確認します。:
[gsc]$ create instance 182.168.1.102 5432; インスタンス:182.168.1.102:5432を作成しました。 [gsc]$ show instance; インスタンス一覧 SERVERID | HOST | PORT | STATUS ------------------------------------------ 0 | 192.168.1.101 | 5432 | 稼動中 1 | 182.168.1.102 | 5432 | 稼動中 [gsc]$
この例では、GSCに接続する際に指定していた「192.168.1.101:5432」に加え て、「182.168.1.102:5432」も登録されたことが分かります。
インスタンスの登録まで完了したら、一旦環境構築ツールを終了し、次にデー タベースとテーブルの作成に移ります。「\q」コマンドで環境構築ツールを終 了することができます。:
[gsc]$ \q Now closing the connection
環境構築ツールを起動してcreate dbコマンドを発行し、サンプルのデータベー ス「sample」を作成します。作成したデータベースはshow dbコマンドで確認 することができます。:
[gsc]$ create db sample(0,1); データベース:sampleを、サーバID:0,1,に作成しました。 [gsc]$ show db; データベース一覧 DBNAME | SERVERID | HOST | PORT ------------------------------------------ sample | 0 | 192.168.1.101 | 5432 sample | 1 | 182.168.1.102 | 5432 [gsc]$
上記の例では、サーバIDが「0」と「1」のサーバ上に「sample」というデータ ベースが作成されていることが分かります。
作成したsampleデータベース上に、以下の5つのテーブルを作成します。:
CREATE TABLE customer ( cust_cd character(10), cust_name character varying(30), post_no character(10), address character varying(50), phone_no character(20), pres_name character varying(20), primary key (cust_cd) ); CREATE TABLE employee ( emp_cd character(10), distcent_cd character(10), name character varying(10), password character varying(20), dept_name character varying(30), primary key (emp_cd) ); CREATE TABLE item ( item_cd character(10) NOT NULL, item_name character varying(30), unit_mony integer, unit_name character(4), stock_num integer, primary key (item_cd) ); CREATE TABLE salesorder ( order_no character(18) NOT NULL, cust_cd character(10), emp_cd character(10), distcent_cd character(10), ent_date date, ent_time time without time zone, supp_date date, sum integer, order_stat smallint, primary key (order_no) ); CREATE TABLE salesordertail ( order_no character(18) NOT NULL, item_cd character(10) NOT NULL, pack_num integer, sepa_num integer, sum integer, primary key (order_no, item_cd) );
まず、open dbコマンドを使用してsampleデータベースへ接続します。:
[gsc]$ open db sample; データベース:sampleをオープンしました。 [sample]>
すると、プロンプトが今までの:
[gsc]$
から:
[sample]>
に変わります。これは、指定したデータベースに接続できた、ということを意味しています。
データベースに接続できたら、テーブル作成のDDL文(CREATE TABLE文)を入 力して、各テーブルを作成します。以下は、customerテーブルを作成している 様子です。:
[sample]> CREATE TABLE customer ( [sample]> cust_cd character(10), [sample]> cust_name character varying(30), [sample]> post_no character(10), [sample]> address character varying(50), [sample]> phone_no character(20), [sample]> pres_name character varying(20), [sample]> primary key (cust_cd) [sample]> ); [DDL] create table customer ( cust_cd character(10), cust_name character varying(30), post_no character(10), address character varying(50), phone_no character(20), pres_name character varying(20), primary key (cust_cd)) [結果]--> 正常に実行されました。 [sample]>
すべてのテーブルの作成が完了したら、結果をshow tableコマンドで確認します。:
[sample]> show table; テーブル一覧 TABLENAME | TABLETYPE | PARTITION_FUNC | STATUS ------------------------------------------------------ customer | 多重化 | | 稼動中 employee | 多重化 | | 稼動中 item | 多重化 | | 稼動中 salesorder | 多重化 | | 稼動中 salesordertail | 多重化 | | 稼動中 [sample]>
環境構築ツールを通してテーブルを作成すると、最初はすべて「多重化テーブ ル」として作成されます。パーティション化テーブルが必要な場合は、part tableおよびpart table2コマンドを使って多重化テーブルをパーティション化 テーブルに変換する必要があります。
作成したsalesorderテーブルを、order_noカラムをパーティションキーとして 二つのパーティションに分割します。多重化テーブルをパーティション化する にはpart tableコマンドを使います。:
[sample]> part table salesorder (order_no) 2; パーティション1テーブル:salesorder を作成しました。
part tableコマンドが完了したら、show tableコマンドにより実行結果を確認 します。:
[sample]> show table; テーブル一覧 TABLENAME | TABLETYPE | PARTITION_FUNC | STATUS ------------------------------------------------------------- customer | 多重化 | | 稼動中 employee | 多重化 | | 稼動中 item | 多重化 | | 稼動中 salesorder | パーティション化 | DEFAULT | 稼動中 salesordertail | 多重化 | | 稼動中 [sample]> show table salesorder; テーブル項目一覧[salesorder] PARTITION_KEY | COLUMNNAME | DATATYPE ---------------------------------------- * | order_no | bpchar | cust_cd | bpchar | emp_cd | bpchar | distcent_cd | bpchar | ent_date | date | ent_time | time | supp_date | date | sum | int4 | order_stat | int2 [sample]>
上記の例では、salesorderテーブルがパーティション化テーブルに変換され、 そのパーティションキーとしてorder_noが設定されていることが分かります。
part tableコマンドで多重化テーブルからパーティションテーブルへの変換を 行うと、すべてのPostgreSQLインスタンス上で、すべてのパーティションを 保持するように変換されます。例えば、2台構成で2パーティションに分割した 場合、2台のPostgreSQLインスタンスが、それぞれパーティション1もパーティ ション2 も同等に保持することになります。
テーブルのデータが大規模になるなど、それぞれのPostgreSQLインスタンス に異なるパーティションのみを保持させたい場合などには、part table2コマ ンドを使用します。
ここでは、salesordertailテーブルを2パーティションに分割し、第1パーティ ションをサーバ0に、第2パーティションをサーバ1に保持させるように設定し てみます。:
[sample]> part table2 salesordertail (order_no) 2 servid=0 partno=(0), servid=1 partno=(1); パーティション2テーブル:salesordertail を作成しました。
パーティション化が完了したら、show tableコマンドで設定を確認します。:
[sample]> show table; テーブル一覧 TABLENAME | TABLETYPE | PARTITION_FUNC | STATUS --------------------------------------------------------------- customer | 多重化 | | 稼動中 employee | 多重化 | | 稼動中 item | 多重化 | | 稼動中 salesorder | パーティション化 | DEFAULT | 稼動中 salesordertail | パーティション化2 | DEFAULT | 稼動中
なお、show priorityコマンド(パーティションの優先度表示)を使用すると、 パーティションの配置状況を確認することができます。:
[sample]> show priority salesorder; 優先度[salesorder] SERVERID | salesorder_00 | salesorder_01 ------------------------------------------ 0 | 0 | 1 1 | 1 | 0 [sample]> show priority salesordertail; 優先度[salesordertail] SERVERID | salesordertail_00 | salesordertail_01 -------------------------------------------------- 0 | 0 | 1 | | 0 [sample]>
2分割したパーティションテーブルであっても、salesorderテーブルと salesordertailテーブルで、パーティションの配置状況が違っていることが分 かります。
テーブルの作成が完了したら、close dbコマンドでデータベースへの接続を閉 じ、「 \q 」コマンドで環境構築ツールを終了します。:
[sample]> close db; データベース:sampleをクローズしました。 [gsc]$ \q Now closing the connection [forest@db0:~]$
Jpsqlは、PostgresForestのJDBCドライバ(仮想化モジュール)を通してデー タベースへのアクセスを行う、psql相当のコマンドラインツールです(ただし psqlと違い、JpsqlではDML文のみに対応しています)。
接続先のGSCのホスト名、ポート番号、GSC名、および使用するデータベース名 を指定して、Jpsqlを起動します。:
[forest@db0:~]$ /usr/local/forest40/bin/Jpsql.sh -h 192.168.1.101 -p 5432 -g gsc -d sample -U forest -W forest JAVA: /usr/java/j2sdk1.4.2_13/bin/java CLASSPATH: /usr/local/forest40/lib/Jpsql.jar /usr/local/forest40/share/postgresforest40.jar /usr/local/forest40/lib/commons-cli-1.0.jar Connection URL : jdbc:postgresforest:GSC=//192.168.1.101:5432/gsc@sample Welcome to Jpsql, the PostgreSQL interactive terminal. Connecting to Database URL = jdbc:postgresforest:GSC=//192.168.1.101:5432/gsc@sample (user:forest) Connected to PostgreSQL 8.1.5 [1]
INSERTクエリでデータベースにデータを挿入します。:
[1] INSERT INTO employee (emp_cd, distcent_cd, name, "password", dept_name) VALUES ('731807 ', 'D01 ', '田中 明雄', '@731807', '1'); SQL:INSERT INTO employee (emp_cd, distcent_cd, name, "password", dept_name) VALUES ('731807 ', 'D01 ', '田中 明雄', '@731807', '1'); Updated 1 rows [2]
大量のDML文を発行する場合には、ファイルから読み込ませることもできます ( 本チュートリアル用INSERTファイル )
[forest@db0:~]$ /usr/local/forest40/bin/Jpsql.sh -h 192.168.1.101 -p 5432 -g gsc -d sample -U forest -W forest -f tutorial_insert.sql [...snip...] Using SQL file input from tutorial_insert.sql SQL:INSERT INTO employee (emp_cd, distcent_cd, name, "password", dept_name) VALUES ('731807 ', 'D01 ', '田中 明雄', '@731807', '1'); Updated 1 rows [...snip...] INSERT INTO salesordertail (order_no, item_cd, pack_num, sepa_num, sum) VALUES ('200301261237560001', 'CO00007 ', 5, 6, 1500); Updated 1 rows [forest@db0:~]$
まず、パーティションテーブルに対する全件検索を実行してみます。:
[6] SELECT * FROM salesorder; SQL: SELECT * FROM salesorder; order_no cust_cd emp_cd distcent_cd ent_date ent_time supp_date sum order_stat 200301021237560001 SU00002 510566 D01 2003-01-02 12:37:56 2003-01-09 10 1 200301041237560001 RE00001 857012 D01 2003-01-04 12:37:56 2003-01-11 20 1 [...snip...] 200301291237560001 RE00006 857012 D01 2003-01-29 12:37:56 2003-02-05 220 1 200301301237560001 RE00007 226115 D01 2003-01-30 12:37:56 2003-02-06 235 1 [7] SELECT count(*) FROM salesorder; SQL:SELECT count(*) FROM salesorder; count 30 [8]
[8] SELECT * FROM salesordertail; SQL: SELECT * FROM salesordertail; order_no item_cd pack_num sepa_num sum 200301061237560001 MA00001 6 7 15000 200301061237560001 MA00002 7 8 3500 [...snip...] 200301301237560001 CO00006 8 9 3200 200301301237560001 CO00007 9 10 2700 [9] SELECT count(*) FROM salesordertail; SQL: SELECT count(*) FROM salesordertail; count 600 [10]
salesorderテーブルは全30件、salesordertailテーブルは全600件のレコード が格納されています。これらのテーブルはパーティション化されていますが、 仮想的に単一のテーブルとして扱われていることが分かります。
次に、特定のパーティションにのみが処理対象となるような検索を行います。 具体的には、先ほどパーティションキーに指定したorder_noカラムを条件に指 定してSELECTクエリを実行します。:
[9] SELECT * FROM salesorder WHERE order_no = '200301021237560001'; SQL: SELECT * FROM salesorder WHERE order_no = '200301021237560001'; order_no cust_cd emp_cd distcent_cd ent_date ent_time supp_date sum order_stat 200301021237560001 SU00002 510566 D01 2003-01-02 12:37:56 2003-01-09 10 1 [10]
この時のPostgreSQLのサーバログを見ると、テーブル名salesorderがパーティ ション名salesorder_01に書き換えられ、このパーティションのみに検索が行 われていることが分かります。:
LOG: statement: <BIND> LOG: statement: EXECUTE <unnamed> [PREPARE: SELECT * FROM salesorder_01 WHERE order_no = '200301021237560001'] LOG: duration: 0.222 ms
このように、パーティションキーを条件に含めることによって、「どのパーティ ションに検索にいくべきか」をPostgresForestのJDBCドライバ内で自動的に判 断して、内部で最適なクエリへの書き換えを行っています。
salesordertailテーブルについては、各インスタンスの保持しているパーティ ションがそれぞれ違いますので、パーティションキー(order_no)以外で条件 を指定して検索された場合には、それぞれのサーバの保持するパーティション に検索を行い、その結果をマージして返却されます。:
[1] SELECT * FROM salesordertail WHERE item_cd = 'MA00001'; SQL:SELECT * FROM salesordertail WHERE item_cd = 'MA00001'; order_no item_cd pack_num sepa_num sum 200301021237560001 MA00001 2 3 5000 200301041237560001 MA00001 4 5 10000 [...snip...] 200301291237560001 MA00001 9 10 22500 200301301237560001 MA00001 10 11 25000 [2]
この時のインスタンス0のサーバログは以下のようになります。:
LOG: statement: PREPARE <unnamed> AS SELECT * FROM salesordertail_00 WHERE item_cd = 'MA00001' LOG: statement: <BIND> LOG: statement: EXECUTE <unnamed> [PREPARE: SELECT * FROM salesordertail_00 WHERE item_cd = 'MA00001'] LOG: duration: 0.541 ms
また、インスタンス1のサーバログは以下のようになります。:
LOG: statement: PREPARE <unnamed> AS SELECT * FROM salesordertail_01 WHERE item_cd = 'MA00001' LOG: statement: <BIND> LOG: statement: EXECUTE <unnamed> [PREPARE: SELECT * FROM salesordertail_01 WHERE item_cd = 'MA00001'] LOG: duration: 0.243 ms
このように、それぞれインスタンスで別々のパーティションに検索を行い、そ の結果をマージして返却していることが分かります。
多重化テーブルへの検索は、特に書き換えなどは行われず、通常のSQLと同様に処理されます。:
[1] SELECT * FROM employee; SQL:SELECT * FROM employee; emp_cd distcent_cd name password dept_name 731807 D01 田中 明雄 @731807 1 510566 D01 岸元 猛 @510566 2 422110 D01 内田 祥子 @422110 3 857012 D01 山本 豊 @857012 4 226115 D01 原 里美 @226115 5 [2]
この時のサーバログは以下の通りです。:
LOG: statement: PREPARE <unnamed> AS SELECT * FROM employee LOG: statement: <BIND>