「やっぱり SQL じゃないと」「リレーショナルでないと」という声をよく聞く。 でも、その人たちが本当に欲しいのは SQL ではないと思う。
SQL を使いたいのではなく、ORM を使いたい
SQL やリレーショナルにこだわる人の大半は、JOIN を自分で書きたいわけではない。 LEFT JOIN と RIGHT JOIN を使い分けたり、そのときインデックスがどう効くかを制御したりしたいわけでもない。
やりたいのは、ORM の find のような API でデータを取ってくること。それがいちばんだ。
「リレーショナルが必要だ」と語られる理由と、実際に使っているものの間には、かなりの距離がある。
「JOIN できない」「インデックスが」は、本当に問題か
Firestore を使わない人は、たいてい二つの理由を挙げる。
- JOIN ができない
- インデックスの制約がある
どちらも事実ではある。でも、ほとんどの Web アプリ、スマホアプリ、AI ツールに、そんな複雑な処理は要らないはずだ。
ユーザーのデータを保存して、一覧を出して、一件を取ってくる。 多くのアプリがやっているのは、ほぼそれだけである。
本当の問題は、ORM という層
ここで分けて考えたい。問題はリレーショナルかどうかではない。ORM という層を入れることにある。
SQL そのものは、何十年もほとんど変わっていない、とても安定した仕組みだ。 変わり続けているのは、その上に載る ORM のほうである。
ORM は、安定するまで何世代もかかる
ORM も、新しいものが出るとそちらに飛びつく人が多い。 しかし ORM が安定するまでには、何世代も必要になる。 使いやすく見える API の裏で設計がまだ固まっておらず、固まるまでの間に互換性のない更新が繰り返される。
破壊的な変更で、バージョンを上げられなくなる
ORM は本当に、数年で互換性のない更新をどんどんする。 データにアクセスするコードはアプリ全体に散らばっているので、ORM の書き方が変わると、直す範囲がアプリ全体に広がる。 その結果、ORM のメジャーバージョンを上げられないプロジェクトが大量に生まれる。
そこで止まっていると、次は言語のバージョンアップについていけなくなる。 古い ORM が新しい言語のバージョンで動かず、言語も上げられない。 こうして、依存関係全体が古いまま固まっていく。
そんなふうにバージョンアップできなくなったプロジェクトを、本当に無数に見てきた。
流行で廃れるものは、セキュリティ上のリスクになる
ORM は流行で廃れる。廃れた ORM は更新されなくなり、脆弱性が見つかっても直らない。 バージョンを上げられないプロジェクトは、直った版にも乗り換えられない。
セキュリティを考えると、ORM はできるだけ入れないほうがよい。
PaaS の DB を、素で使う
だから、PaaS の DB を素で使うことを、本気で検討したほうがよい。 ここでいう「PaaS の DB」は、Firestore のようなドキュメント型に限らない。マネージドの Postgres や MySQL のような RDB も含む。
- Firestore のようなドキュメント型 —— 提供元の SDK でそのまま読み書きする
- マネージドの RDB —— ORM を挟まず、薄いドライバーから SQL をそのまま投げる
RDB を素で使うときは、値を文字列で連結せず、プレースホルダーで渡すこと。 SQL インジェクションを防ぐために ORM が要るわけではない。
どちらを選んでも、得られるものは同じだ。
- 自分で運用するより落ちにくい —— サーバーの面倒は提供元が見る。PaaS にも障害はあるが、自分で抱えるよりはるかにましだ
- バージョンアップをあまり気にしなくてよい —— データベース本体の更新は提供元が受け持つ。間に挟まる ORM がないので、ORM の破壊的な変更に振り回されない
SDK も変わる。それでも層は少ないほうがいい
正直に書いておくと、PaaS の SDK も破壊的な変更をする。 たとえば Firebase の JavaScript SDK は、v8 から v9 で書き方が大きく変わった。
それでも、「ORM」と「ドライバーや SDK」の二層を抱えるより、一層のほうがずっと軽い。 上げられなくなる可能性のある依存が、一つ減るからだ。 RDB に SQL を素で投げるなら、変わりにくい SQL の上に薄いドライバーが一枚あるだけになる。
リレーショナルが本当に必要な場面
もちろん、リレーショナルが本当に必要な場面はある。
- 複雑な集計や分析をアプリの中で頻繁に行う
- お金や在庫のように、複数のデータを厳密に一度に更新しなければならない
- 業務アプリで、管理画面や集計の要望が後から来ることが見えている
こうした場合は RDB を選べばいい。ただし、そこでも ORM を入れる必要はない。マネージドの RDB に SQL を素で投げればよい。
逆に、ドキュメント型を選ぶと、JOIN しない分の手間はアプリ側に来る。 データを重複させて持つことになり、名前を一つ変えたときに複数の文書を書き換える、といった整合性の面倒を自分で見ることになる。 どちらを選ぶかは、自分のアプリが何をするかで決めればいい。
「SQL じゃないと」と言う前に、自分が欲しいのは SQL なのか、ORM の find なのかを確かめてみてほしい。
そしてどちらのデータベースを選ぶにしても、ORM を入れる前に、PaaS の DB を素で使うことを候補に入れてほしい。





