RDBは何故不要か

昔書いたものが発掘されたので仕立て直す。どうも「なあ、RDBってなんでこんなどこでも使われてるんだ？」と聞かれて書いたものであったらしい。この度その友人の三回忌があったので供養代わりである。
なお、内容は下記に要約したとおりなので「せやな」と思えるなら読む必要はおそらくない。

TL; DR:
**制約設定しろって言ってんだろ。使わねえならDBやめちまえよ。**
いや例外がないとはいわないけど。

---

あるありふれた技術の導入を考えるとき、まっ先に考えるべきは、まずその**不要性**である。
ここでいう不要性とはまさしく必要性の反対であり、いかなる時いかなる理由により不要となるか、今まさに不要となっていないか、という事実を考えるものだ。
……というのは単に建前であり、実のところ個人的事情として「強みを探す」よりも「弱みをあげつらう」方がよほど得意でありモチベーションとして有力である、というしょうもない事情に起因するのが悲しいところではある。まあバカとハサミは使いようということで許してほしい。

なおここで「ありふれた技術」と前置きしたのは、ウン十年前はともかく現在となっては適当に[^1]オープンソース系から拾ってくれば済むRDBであるならばともかく、進歩の早いフロントエンドや最先端を行く機械学習などの界隈において、不要性だなんだとのたまっていては即座に敗北主義者扱いからの銃殺刑ならぬ解雇通告待ったなしだからである。
……というのも本来冗談なのだが、実際のところ、大抵そういうことをのたまうやつはよっぽど「どう考えてもそれいらねえだろ！」でもない限りそうした方がよいことがおおいので笑えない話なのだ。

# 制約
さて、RDBというものの最大の特性が何かと聞かれれば、これを非常に大雑把に「**制約**」であると回答して怒る人間がどれほどいようか。
意図をきっちり説明しきったあとのことと仮定すれば、私はいないと信ずる。

RDBというものは基本的に**レコード**というものを一つの単位とする。レコードが複数集まると**テーブル**だ[^2]。レコードというのはいわば「書類の一枚」であり、テーブルは「同種の書類を集めた束」であると通りがよい。
テーブルというからには行と列がある。縦と横だ。レコードは行であり、列、つまり縦の方は**カラム**という。カラムは情報そのものの「種類」と「意図」から予め決定されており、要するに決まったものだけが入る。
以てレコードの各情報が常に「正常なデータが入っている」または「何も入っていない」状態に保たれることによって、データベースに格納された全情報は正常であろうと**推定**できる。これがRDBの各機能を限界まで取っ払ったところにある根本的な概念のひとつである。

例えば、私が今所属する会社はありがたいことにしっかりと給与明細を発行してくれている[^3]。
月給制の会社員であれば、給与明細には少なくとも年月、支給日、氏名、基本給、各種手当、保険料、年金、税、勤怠情報、あたりが記されているはずで、これらから導き出される総支給額、控除額、差引支給額 (つまり手取り) も同様に記されている。
今挙げた「記されているであろう情報群」は全て「その情報の意図」である。当然だ。人間にとって給与は金額であり、単なる数字ではない。
しかし残念ながらコンピュータは意図を斟酌してくれない。教えなければ給与をUnix時間で処理してもおかしくはないし、氏名を数値として扱ってもおかしくないし、そもそも全部捨てることだってありうるだろう。
そこで我々人間は「種類」、馴染み深い用語で言えばデータ型を持ち出す。氏名は文字列であり、給与は数値であり、年月は日時あるいは文字列ないし数値2つだ。こうしておけば少なくとも給与欄にはるか昔の日時が出てきて暗号解読に励む必要はなくなり[^4]、私は妙な換算作業をすることなく家計簿に支給額と控除額を書けるのである。

更に、RDBのRはRelationalのRである。リレーショナル・データベースのリレーショナルたる所以は**テーブル同士に相互関係を定義できる**点にある。
この相互関係はもちろん制約として機能する。給与明細の例で言うならば、「氏名は空にならず、社員テーブルに存在するもの以外入ることはない[^5]」あたりだろうか。

さて、ここまで出てきた概念が全て制約の一種であるということに異論を挟むのは難しいだろう。
もちろんこれだけであれば人間にもやってやれないことはない。
事実国家組織の官僚や銀行職員がコンピュータとネットワークの登場以前にやっていたことはまさにこれの紙とペンバージョンであり、断言するが今でも完全には廃絶されていない。極端な話我々が買い物をした後受け取る感熱紙のレシートでさえこれの一種なのだ。
重要なのは、RDBが「RDBの文脈において」この制約を固持し、遵守し、保証してくれるというその一点である。
コンピュータは間違えない。人よりは。

# 隠蔽
さて、RDBがデータを保持してくれるとはいえ、そのままさらけ出していては保証もなにもない。炎天下で売り物のボトルを外にほっぽりだしているようなものである。ぬるくなっているどころではなかろうし、そもそもどういじられているかわかったものではない。
「ある制約を保証 (ないし保障) せよ」と言われた場合、これを達成するためには必ず隠蔽が必要になる。隠蔽と言っても単に隠すという意味ではない、というのは言うまでもないことだろう。この場合の隠蔽とは入出力の隠蔽であり、これによる間接的なデータ実体の保護である。オブジェクト指向と同じだ。

RDBは保持すべしと預けられたデータを自らの知る形で保存する。その形式も内容も人の知るところではない[^6]。
RDBは要求されたデータを要求された形で提供する。しかし内部で如何様な処理を行っているかは人の知るところではない。

自然、RDBとの対話は宣言的なものとなる。いわゆる「宣言型プログラミングとはSQLのようなものである」という話はここから来ている。宣言的である、というのは要するに「中はどうなっているか知らんが、俺はこういうものをこういう形式で欲しているからよこせ」ということだ。

# 検索
さて、RDB最大の特性は終わったが、最大の利点がまだである。それは**検索**だ。
RDBは数千、数万、数億と兎角大量のレコードを積み上げる事ができる。先程はレコードを給与明細という書類の一種に例えたが、例えば数億もの給与明細があったとなると、これはそもそも置く場所すらないというのが現実であろう。
しかしRDBの保持するレコードは物理的に存在する書類ではない。我々も親しみ深いバイナリである。どのようなフォーマットかはともあれRDBMSによって維持管理され、適宜整理されてすらいる。するとどうだろう。検索が可能になるのだ。
「制約が検索をもたらす」というのは少々因果が逆転しているようにも思うが、技術的にはむしろ当然の帰結であろう。整理されていないものから探し出せ、というのは困難を通り越していじめである。

RDBは一般的にSQLと呼ばれる専用言語を以て検索 (だけではない) 命令を受け付ける。SQLは一見複雑だが、要するにcdやlsやrmと同じコマンドの一種である。断言するが、SQLそれ自体は単に文法がやたら凝っているだけであり難しくない[^7]。
RDBMS、特にガチの業務用として使われるものは優秀である。よろしくないデータ構造、よろしくないSQLで数億件のレコードを検索して終わるまでたったの2分で済ませる。もちろんこれを実際業務で使うと「遅い」と文句が出るのは誰がどう見ても必定なのだが、「整理の仕方がまずいやたら巨大な倉庫を出来の悪い地図で探し回って2分」と考えるとむしろ優秀どころの騒ぎではない[^8]。
結果、晴れて世の中はRDBで溢れかえったのである。

# 不要性
さて、そろそろ眠くなってきたのでいよいよ不要性について書いてシメとする[^9]。
もう書くまでもない気がするが、結論から言えばRDBは「(制約)|(検索)の(不要)|(しようがない)もの」に対して絶対に不要である。

これは例えばアップローダのようなものであろう。
アップローダとは、何らかのファイルを一時的に保持し、主にインターネット経由で受け渡すためのものである。
究極的にはアップロードされたファイル、そしてファイルを取り出すための識別子だけがあればよい。それ以外の一切は不要だ[^10]。
RDBが直接ファイルを保持する必要もない。RDBにはLarge OBject略してLOBの取扱機構が備わるものが多いが、そもそもの問題としてファイルに制約を掛けることは現実的に不可能であるし、検索も同様だ。「図書館の書庫からこういう記述の本を探せ」と言われたら絶望するほかあるまい[^11]。
しかしどちらかというとこれよりも問題なのは、使う側の無知と無能である。

例えば「予備カラム」と呼ばれる悪名高きアンチパターン。テーブルを定義する際にはカラムを定義しなければならないのがRDBだが、そこに「あとで増えたとき困る」というわけのわからない理屈でもって「予備カラム1」「予備カラム2」「予備カラム3」……などとやることである。
賭けてもいいがろくなことにならない。ろくなことにならなかった例を挙げることはいくらでもできるが、逆に成功した例はとんと聞かない。
かろうじて「いろいろな使われ方をする想定だから、 (当該ソフトウェアの) ユーザ向けの予備として」という形で使われていた例は比較的マシな部類であったということは認めてもよいが、それでさえも**制約を自ら放棄している**というその一点でもって無能の誹りを免れ得ないものであろう。というか、事実ろくなものではなかったのだが。

例えば単に「制約なんて意味ないだろ」という無理解からくるパターン。制約なんてどうせ接続するソフトウェアの側で実現するのだからどうでもいい、というタイプである。もちろんそれも一つの戦略だろう――**作るソフトウェアとメンテナンスするオペレータが完璧であるなら**。
人間は間違える。間違いの量と危険度は操作と思考の複雑性の積に概ね比例する。そしてソフトウェアを作るのに比べ、RDBの制約設定は操作も思考も明らかに単純である。仮に古のステップ数時代よろしく複雑性がコード量に比例するとすれば、たかが知れているDDLと天井知らずのソフトウェアどっちがマシかは考えるまでもない。なお、このパターンも見たがやはりバグりまくっていた。

これらに例外があるとすれば、恐らくそれはSQLiteぐらいのものであろう。[条件によってはファイルシステムより早いという記事](https://postd.cc/faster-than-fs/)すらあるほどだし、搦手としてはあるかもしれない。

# むすび
* **制約を設定せよ。制約が要らないと思うのなら、RDBは必要ない。**
* **検索せよ。検索が要らないと思うのなら、RDBは必要ない。**
* **LOBは邪道である。制約にも検索にも向かない。**

[^1]: もちろんここでは本来の方の意味。つまりライセンスに注意し、リリースノートを注視し、コミュニティに敬意を払いつつ随時アップデートを確認しながら、ということになるか？ なおこの当時どうだったかは忘れたが、最近ではOracleから逃げながらDBを使うのも地味にきつくなってきた (恨み言) 。
[^2]: これはどう考えても順序が逆転しているが、混乱を避ける意味ではもっとも都合がよい説明だろう。
[^3]: 当然？ 当然を当然に処理してくれるというのはありがたいことだ。
[^4]: 昔の所属で1度あった。冗談のような話だが。
[^5]: この制約を字句通り受け取るとデータベースは崩壊するのだが、まあそこはいわゆる論理削除パターンでやっているかなにかだと思ってほしい。面倒だ。
[^6]: もちろん、ここでいう人とはRDBのユーザのことだ。RDB本人 (？) からすれば、開発者とは即ち神であろう。
[^7]: その「文法がやたら凝っているだけのコマンド」をまともに使えると言えるようになるまで5年かかっているのは内緒である。しょうがねえだろgroup byが何度やってもしっくりこなかったんだ。
[^8]: もちろん、しょぼいやつだとこの千分の一の規模でも40分以上かけたりするのだが。
[^9]: 原文ママ。これ書いた当時も夜に書いていたのか、私は。
[^10]: 非常に割り切った話だが、これを突き詰めるといわゆるマイクロサービスの系統にどんどん近くなっていく。会員制にしたい？ それは認証/認可サーバを立ててそちらに任せろ、といった具合。
[^11]: もっともそれ故世の中には全文検索専門のシステムがあったり、RDBに全文検索機能を追加するアドオンがあったりするわけだが。