LoginSignup
17
17

More than 5 years have passed since last update.

【少しずつ追記】XMLデータベース「BaseX」のインストールからベンチマークまで

Last updated at Posted at 2016-01-19

XMLデータベース「BaseX」のインストールからベンチマークまで

前書き

がっつり正規化されたRDBMSでテーブルの山を見て嫌になっちゃいました。
階層化されたデータを表現するために、親IDを格納するカラムを作って、再帰的に親や子を探すのにも疲れちゃいました。
大体そういうデータはRDBMSには向いてません。ドキュメントベースでスキーマレスなデータベースで行きましょう。

ドキュメントベースのDBとして私が思いついたのは、

  • XML が基本となる「BaseX
  • JSON が基本となる「mongo

あたりでしょうか。どちらもオープンソースです。
プロプライエタリなものでスッゴイものもあると思いますが、貧乏なのでお金がかけれません。

しかし、私の探し方が悪いのか、何故かどちらも日本語のドキュメントが少ない。

今回は「BaseX」に挑戦してみます。
構築しながら、ハりそうな(ハマった)ところなんかもメモしていければと思います。

-- 2016-01-19 23:27

インストール

私の環境はArch Linux なので、一発です。

yaourt -S basex

多分、Ubuntu、Debian なんかも

apt-get install basex

でいけるんでないでしょうか。試してません。

Fedora、CentOS あたりは、yum のリポジトリを追加しないといけないかもしれません。
CentOS6 の時は追加しないといけませんでした。
以下のような内容のファイルを /etc/yum.repos.d/base.repo みたいな感じで作成します。
Fedora22の例です。

/etc/yum.repos.d/basex.repo
[home_basex_opensuse]
name=BaseX openSUSE Build (Fedora_22)
type=rpm-md
baseurl=http://download.opensuse.org/repositories/home:/basex:/opensuse/Fedora_22/
gpgcheck=1
gpgkey=http://download.opensuse.org/repositories/home:/basex:/opensuse/Fedora_22//repodata/repomd.xml.key
enabled=1

本家のサイトのダウンロードのページからコピってきました。Fedora23のリポジトリは書いてありませんでした。しかしなんで Suse なんだろう?
作成したら、

yum install basex

で、多分いけると思います。

インストールされるバイナリが、 9.92MB ! ちっちゃいなぁ…。
BaseX はJava で書いてありますので、依存関係でJava がインストールされるかもしれません。

あれ?起動方法がわかんない。

-- 2016-01-19 23:44

起動

CentOS の場合、/usr/bin 以下にインストールされています。
Arch Linux の場合、/usr/share/java/basex/bin にインストールされていました。
というかGUIのメニューに basexgui が登録されていました。

コマンド 内容
basex スタンドアロンの対話モードで実行
basexgui GUIのクライアント
basexclient Client/Server モードのクライアント
basexserver Client/Server モードのサーバ
basexserverstop サーバで起動したbasexを停止
basexhttp よくわかんないので今度にする
basexhttpstop http で起動したbasexを停止(多分)

まずは素直にメニューからGUIクライアントを起動。

Spectacle.GzU947.png

素敵な画面が出てきました。これがあれば開発も楽そう。
ん?
これ、リモートのbasexサーバに繋げないのかな?
あとで考える。

スタンドアロンの対話モードもOK。

サーバの起動は、

/path/to/basex/bin/basexserver -S

ポートは1984がデフォルト。起動時に-pオプションで変えられるようです。
その他のオプションは--helpで。

起動スクリプトなど気の利いたものは用意されていません。
systemd の起動スクリプト書くのもめんどいので、/etc/rc.local に起動コマンドを書いて、rc.local のエグゼキュートビットを有効に設定。
これでOS起動時に自動的にサービスが起動するはず。

クライアントで接続してみる。ローカルホストなら省略できますが、

/path/to/basex/bin/basexclient -n localhost

パスワードが聞かれた。そんなの知らんぞ…。
http://docs.basex.org/wiki/Startup#Client.2FServer
ちゃんと書いてありました。
Username: admin
Password: admin
です。
しかし、あぶねぇパスワード。変えておきましょう。
ログインしたあとに、

> PASSWORD

一旦ここまでで、再起動してみます。

-- 2016-01-20 00:52

起動成功。今日はもう眠い。続きは明日。

-- 2016-01-20 00:59

CREATE DB してみる

basexclient でローカルホストの basex サーバに接続して新規のデータベースを作成してみる。

> CREATE DB testdb
> XQUERY /
Stopped at ., 1/2:
[XPDY0002] root(): no context value bound.

ありゃ?
あぁ、ちゃんとOPENしないとダメでした。

> OPEN testdb
Database 'testdb' was opened in 1.48 ms.
> XQUERY /

Query executed in 0.3 ms.

次にデータを突っ込んでみる。
いきなりつまずいたが、データを突っ込むには先ほど作成したデータベース「testdb」の中にxmlを作らないといけないらしい。

> ADD TO sample1.xml "<root/>"
Resource(s) added in 71.61 ms.
> LIST testdb
Input Path   Type  Content-Type     Size  
----------------------------------------
sample1.xml  xml   application/xml  2      

Resources.
> XQUERY /
<root/>
Query executed in 0.55 ms.

出た。でも xml は指定してないぞ?

> ADD TO sample2.xml "<root2/>"
Resource(s) added in 6.98 ms.
> LIST testdb
Input Path   Type  Content-Type     Size  
----------------------------------------
sample1.xml  xml   application/xml  2     
sample2.xml  xml   application/xml  2     

Resources.
> XQUERY /
<root/>
<root2/>
Query executed in 1.16 ms.

なるほど。カレントのDB内のxmlすべてが検索対象なのね。

> XQUERY doc("testdb/sample1.xml")/root
<root/>

こうすれば、特定の xml ファイルに対して XQUERY が発行される。
DB名は省略できないらしい。めんどくさい。
OPENしていない状態でも実行可能。
ちょっと削除してみよう。

> DELETE /
0 resource(s) deleted in 1.76 ms.
> xquery /

Query executed in 0.35 ms.
>
> LIST testdb
Input Path  Type  Content-Type  Size  
------------------------------------

Resources.

ぎゃーーーー。全部消えた!
DELETE 、これは恐ろしいコマンドだ…。

くじけてしまったので、一旦 basexclient から抜ける。

ところでBaseXのファイルはどこにあるんだろう?

/root/BaseXData にあった。
実行したユーザのホームディレクトリにできるようだ。
そのディレクトリに下にDB名のディレクトリが作成され、その中には *.basex のファイルがあるけどバイナリのようだ。
これDBがでかくなったらどうなるんだろう?
それから、私のOSの場合、/root のファイルシステムはBtrfsなのだが、CoWの影響も気になる。
ま、でかいDB作ったあとでCoWを無効にして試してみよう。

少ししか試せなかったけど今日はここまで。
ベンチマークに使えそうな巨大な xml ファイルを探してこよう。

-- 2016-01-21 01:22

データ投入

速度を測るにもデータをぶち込まなければ始まらない。
巨大なのxmlをダウンロードして来てぶち込んでみます。

その前にPCスペックは、
CPU Core i7-3930K 3.20GHz
メモリ 32GB
ディスク /root/BaseXData がある領域は、SSD 2台を Btrfs で RAID0 構成

インポートするファイルは、wikipedia のYahoo向けabstract、1.7GB

> add to wiki.xml /tmp/jawiki-20160111-abstract.xml
Resource(s) added in 102797.21 ms.
> XQUERY count(/feed/doc)
1603475
Query executed in 384.85 ms.

ほう、意外と速い。
検索してみる。

> xquery count(feed/doc/title[contains(text(),'ガンダム')])
1179
Query executed in 2191.71 ms.

キーワードについては見逃してください。そんな世代なんです。
BaseX はJava で書かれているので、日本語もばっちり。

インデックスを作ってみる。

> CREATE INDEX TEXT
Index 'TEXT' created in 24116.67 ms.
> xquery count(feed/doc/title[contains(text(),'ガンダム')])
1179
Query executed in 2122.68 ms.

あんましかわらん。私が想像してるインデックスとは別物なのか。

> CREATE INDEX FULLTEXT
Out of Main Memory.

うぎゃー。
ちなみに実ファイルの方は、

-rw-r--r-- 1 root root  25M  1月 21 02:34 atv.basex
-rw-r--r-- 1 root root    4  1月 21 00:23 atvl.basex
-rw-r--r-- 1 root root    0  1月 21 00:23 atvr.basex
-rw-r--r-- 1 root root  628  1月 22 00:01 inf.basex
-rw-r--r-- 1 root root   11  1月 21 02:34 pth.basex
-rw-r--r-- 1 root root   28  1月 21 23:59 swl.basex
-rw-r--r-- 1 root root 795M  1月 21 02:34 tbl.basex
-rw-r--r-- 1 root root 1.6M  1月 21 02:34 tbli.basex
-rw-r--r-- 1 root root 1.3G  1月 21 02:34 txt.basex
-rw-r--r-- 1 root root  43M  1月 21 23:58 txtl.basex
-rw-r--r-- 1 root root  29M  1月 21 23:58 txtr.basex

Btrfs の CoW を無効にしてみました。

# mv BaseXData BaseXData_old
# mkdir BaseXData
# chattr +C BaseXData
# cp -a BaseXData_old/* BaseXData
> xquery count(feed/doc/title[contains(text(),'ガンダム')])
1179
Query executed in 1827.73 ms.

少し早くなった。

もっと複雑な検索も試してみたいとこなのですが、結構いけるんではないでしょうか?

しかし、XQuery、XPathは難しいなぁ…。

-- 2016-01-22

PHPから接続してみる

PHPから接続するには、BaseXのClientsのページからBaseXClients.php をダウンロードしておきます。
で、PHPの手抜きなサンプル。
(手を抜いてないサンプルは、上記のリンクからもダウンロードできます)

sample.php
<?php
// クラス定義ファイルのインクルード
include_once("./BaseXClient.php");

// DBへの接続とデフォルトDBのオープン
$session =  new Session("localhost", 1984, "username", "password");
$session->execute("OPEN testdb");

// クエリの発行
$input_xpath = "feed/doc/title[contains(text(),'ガンダム')]/text()";
$input_flwor = "for \$i in feed/doc/title where contains(\$i/text(), 'ガンダム') return \$i/text()";
$query = $session->query($input_flwor);

// データの表示
while($query->more()) {
    print $query->next() . "\n";
}

// クエリとDB接続のクローズ
$query->close();
$session->close();

クラス名がSession とか、xquery 内で改行が使えないとか、気に入らないところも…。
まぁラッパー作っちゃえばいいんですが。
あと、クラスの中でsocketが使われているので、PHP がsocket オプション付きでインストールされている必要がありそうです。

とりあえずここまで行けたら、必要なデータをxml とJSON とSQL でファイル出力していろいろ比較できそう。

-- 2016-01-24 23:12

17
17
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17