「Lisp型」NoSQL DBMS、Briqsを作ってみた

####最新のドキュメントはこちら

ここの文章のまとめをはじめ、チュートリアルなどがあります。
http://qiita.com/Aurola_Japan/items/596ecc17fc4c8f9f7c3e

ソースコードも公開しています。
http://qiita.com/Aurola_Japan/items/0d5d037fed7d91120887

ですのでここの文章は最早あまり意味がなくなってしまったのですが、心情的なことを書いているのはここだけですので、よろしければどうぞ。

####元々の文章
自分がこの一年を掛けて実装したのは、一言で言えば、NoSQLデータベースシステム、になるだろう。もう少し詳しく言うと、技術的にはkey-value storeということになるかもしれないが、思想的には多分グラフデータベースを目指している。機能的にはCouchbaseが目標。

このDBMSにはBriqs、という名前を付けた。レゴブロックが大好きなのだが、そのブロックは英語でBrickで、そこからの命名。

Briqs内では、扱うデータは全てBriqという単位になる。Briqは型を持っているので、通常DBMSで想定されるようなデータ型は持てる(現在実装は一部)。

さて…ここからが、Briqsの売りというか、中心的なアイディアである。Briqの中には、Cellという名前の型がある。これは他のBriqへのポインタorファイル内でのindexを持っている。簡単に言うと、うろ覚えだがRiakのLinkみたいなもの。Lispのコンスセルでもよい。

Briqs内では、データとデータのつながりを、このCell型Briqによって行う。因みに完全にコンスセルを意識していて、Cellはcarとcdrにあたる二つのリンク(内部ではcarをL、cdrをGと呼んでいるが)を持っている。これによって好きなデータ構造を自分で作り出せる。

ここまでが、一つ。次のポイントは、このBriqが持つクエリ言語のことである。これにはStiqと名付けた。Briqとの語呂合わせだが、「魔法のステッキ」になれば良いな、と後付けで思いついて採用。

そして、このStiqは、構文はLispであり、それがこのBriqsの第二のポイントとなる。なぜなら、Lispの構文であれば、Cell型Briqを持つデータ構造を、そのままS式で書き下せるからだ。因みに、そのS式ごと、保存でき、再帰的にBriqを作り出せる。

そして更に、この「S式がそのままデータとなってBriqs内に保存される」という性質を進めると、「クエリ言語の内容そのものをデータとして保存できる」ということになる。VM用の中間形式に変換するようなイメージ。

そこで、事実Stiqでは他のファイルに書かれたソースコードをimportできるが、それは結局一度対象のS式をBriq形式で保存して、データとして読込、更にevalし直しているに過ぎない。

DBMSのクエリ言語でプログラミングができて、それを後から自由に呼び出して利用可能、ということは、つまりこれはstored functionを書ける、というのと同じことだ。

ただ特殊なのは、そのクエリ言語の要素自体が、そのDBMSがそのまま扱えるデータ形式(Briq)である、ということだろう。

メモリ節約のため、BriqsでCell型Briqを伝ってデータを走査していく際は、必要な時だけメモリにロードされる。簡易mark-sweepGCも作ったが、まだこれをどのタイミングで呼び出すのかは決めていない。Stiqのインタプリタ内では何度か切りの良いタイミングでGCしている。

現在、Briqsはテストのためにクラウドに置かれていて、Node.jsのアドオンとして動いている。Stiqで簡単なTodo用のAPI（というか単なるLisp関数だが）を作って、それをiOSクライアントから呼び出してJSONにして返却するようにしている。

そもそもBriqs自体はクラウドに乗せたかったものなので、じゃあNode.jsにしようと決めて、アドオンがC++で作るのを知って、そこからC++をちゃんと書き始めた。結構がんばったが、GCがない言語をガッツリやったのは正直初めてでひえーってなった

ちょうど一年前だが、作り始めた時はまだBriqsという名前もなく、しかもD言語で作っていた。D言語もこの時初めて触った。GCがあるけどnativeな実行ファイルを作れる言語で、しかも新しいし、やってみたかったので。実際D言語は便利だった。

だからC++に移植する時は、「D言語だったらあれができるのに……」と感じたことがたくさんあった。でもC++ならiOSでもAndroidでも使えるし、メリットは多いので、諦めてガッツリやることに決めた経緯がある。

Node.jsは最近コミュニティが揉めているがそれはともかく、単にクラウドでDBを動かす方法にそれを選んだだけで、まだよくわかっていない。ファイルIOも独自でやっているので、Node.jsの非同期IOは全く活かせていない。もったいない。ちなみに通信はHTTPですらなく、TCP。

クラウド上で多数のアクセスをさばけるのかどうかは、現在、完全にNodeに任せている。いまのところ、別に自分が使えれば良いので。むしろ性質としてはモバイル端末のキャッシュ用として、Realmみたいな位置付けの方が近いのではないか、とも思う。

そもそも、なぜNoSQLなDBMSを作ろうと思い立ったのか。既存のものではだめだったのか。もちろん既存のものでも良かったのかもしれないが、どれもどこか自分の考えているものと違う、それならば作ってみればよい、ということが最初の動機だった。ちなみに一番近かったのはCouchDBである。CouchBaseLiteも入れてみて、サーバーとモバイル端末の間で、何もしなくても自動的にデータが同期されることに喜んでいたが、クエリを書き始めて、「別にMapReduce要らんのよな」と思い始めてしまって、そこでやめてしまった。Webアプリを作る機能そのもの、というかそのJavaScriptのソースコードをCouchDBそのものに保存してしまう、というアイディアはとても素晴らしいと思ったし、Briqsにも反映されている。

次に参考にしたのは、グラフデータベース、主に情報を見たのはneo4jである。NoSQLと聞くと最初は、「多数のデータをRDBMSはさばけない、そこで正規化を崩して早くデータにアクセスできるように」という印象が強く、「なーんだ、JOINはあんまり得意じゃないのかな」と思い込んでいた時に、出会ったのがneo4jだった。

そういえば、Briqsを作ろうと決意したのは、neo4jのおかげである。それはO'ReillyのGraph Databasesという電子書籍を読んだ時だった（ちなみに編集前のEarly Releaseで、無料だった）。そこにはneo4jの内部構造が書いてあり、「いかに素早くグラフネットワークを走査するか」ということが書いてあって、見つけた時は思わず「これだ！」と叫んでしまった。別に技術的には対したことではないのだが、neo4jが実際にそうやって作られているのなら、自分もその方法でいけるだろう、と確信してやっと作業を始められたのである。ちなみにBriqsでは、基本的には同じアイディアで、どのBriqにもO(1)でアクセス可能である。

ただし、この「どのBriqにもO(1)でアクセス可能」という点以外は、Briqsは現在、グラフデータベースっぽくはない。やろうと思えばグラフデータベースにもなるだろう、というのは、S式でグラフが表現できるだろう、というのと同じぐらいの意味しかない。現在は木構造しか扱っていないので、そういう使い方をするならば、グラフ走査のアルゴリズムは入れないとたぶん使い物にはならないと思う。

上にも書いたがソースコードはC++で書かれているし、できれば公開したいのだが、なにせGitHubアカウントは持っているだけで、オープンなリポジトリを作ったことはない。というかそもそもCUIにもそれほど慣れていない、makefileも最近はじめて自分で書いたとか、linuxのコマンドもまともに使えないとか、そういう人間である。普段はSIerで業務用のiOSアプリを書いているのだが、そこではやらないことばかりで、随分スキルアップしたように思う。g++のオプションとか、Xcodeで今見たら随分意味が分かるんやろうなあ。

というわけで、このBriqsは、萌芽的な動機を合わせれば、かれこれ4年ほど、試行錯誤しながらようやくできたものである。その割には技術的には全く大したものではないのが情けないが、それでも中心的なアイディアは気に入っている。

前職ではずっとRDBMSと戦う人間だった。そのうちに生まれたたくさんの疑問が、Briqsの源泉となっている。その前職を辞め、もう4年ほど前、いきなり一人でiPhone OS 3.x SDKでアプリを作り始めた時も、わけがわからないままCore DataやCocoaのオブジェクトアーカイブ機能やSQLiteを使いながら、「なんか違う」と思い続けていた。上記の既存フレームワークにBriqsの機能的なものをラップして乗せようとしても、遅くて使い物にならなかった。自分は、できるだけ柔軟なデータを、できるだけ簡単にクラウドで扱いたいだけなのに。そういう意味ではiCloud+Core Dataのクソっぷりには本当に泣かされた（もしや、今はちゃんと動いているんかな）。あれが使い物になっていたらBriqsは存在しない。

さて……、問題は、Briqsをなんと呼ぶか、である。結局迷ったあげく、「Lisp型NoSQL DBMS」と書いた。なんなんだよこれは。「S式DBMS」の方がより正確だと思うが、どちらにせよ元々この界隈に関心のある人にしか通じない書き方である。この文章もそうなってしまっている。徐々に整理して、Briqsのことを説明していくようにする予定である。ただ、今は他のことを済ませなければならない。こいつのせいで生活のかなりの部分が犠牲にされてきたのは、間違いない事実（とは言え、自分が勝手にやったことだから仕方ない）なので、これからは現実と折り合いを付けていかなくてはならない。

もしこの文章を読んでくれた奇特な方がいるのなら、お礼を申し上げます。本当にありがとうございました。