ベンチャー社長で技術者で: オブジェクト指向言語で処理したら保守性が悪い!.

というのを目にした。要するに「OO言語+RDBな組み合わせ」において、O\Rマッピングに頼らずにちゃんとSQLとストアドを書いた方がいい、と言うことである。

L.starは元々Java屋でそれからSQLに移ったので、未だに自分が両方をバックグラウンドに持つ人間だと思っている。O/Rマッピングのイ ンピーダンスミスマッチを解決する簡単な方法が実は無い、と言うぐらいには両方を理解している。だからこそ言いたいが、この文章、特定のDBが中央に鎮座していて、それがすべての中心になるような業務システムにおいては完全に正しい。ただし、元々そう言うシステムを念頭に置いて書かれた文章であるので、その点はちゃんと考えるべきだ。O/Rマッピングに頼り切って、SQLをきっちり書かない、ということをすると性能が出ないというのはその通りである。

しかし、その主張に熱心になる余り、若干言い過ぎだろう、と言う部分も多々ある。

SQL-RDBMSというのは実に多様な側面を持った、というか明らかに持ちすぎたソフトウェアである。それらをちゃんと分離せずに論ずるのは危険だ。

要点がばらついているのでどこを引用すればいいか迷ったが、とりあえずここを。
オブジェクト指向言語で処理していればロジックが再利用し易いとか言いますけれど、ちゃんと設計していればストアドプロシージャの方がもっと再利 用し易い。例えば、他の言語でバッチ処理を書いても、エクセルマクロでアドホックな帳票を作るにしても、データがRDBMSにある限りロジックの再利用が 可能になります。

企業のシステムにとって、プログラムよりデータ(構造)の方が長生きなのですから、アクセス方法はRDBMSに入っている方が将来性がある。

「データ構造」のほうがプログラムより長生きだ、ということは多くのケースで間違いないのはその通りだ。が、果たしてストアドプロシージャは「データ構造」だろうか。いやもちろんプログラムである。だからここには「データストアとしてのSQL」と「プログラミングプラットフォームとしてのSQL」という2つの側面が登場する。データストアとしてのSQL、というかリレーショナルモデルを格納するシステムは安定している。実際に正しいテーブル構造を変えなければいけない、ということはまずない。しかし、これがプログラミングプラットフォームとしてはいささか怪しい。

SQLをごりごり書く、というのは意外にもアセンブラでのプログラミングに似ている部分があると言うことだ。SQLは前にも指摘したが、基本的に論理構造と物理構造を分離できない言語であるのに、物理構造を理解したチューニングが必須とされる。チューニング結果としてはき出されるSQLは、あらゆるものに依存しまくりの美しくないものである。これを果たして美しいというか。再利用性が高いというか。賭けてもいいが、自分が書いて自信があったものですら、1年後に見たら吐き気を催すような代物に化ける。他のプロジェクトに再利用できるか、というのはデータ特性とかにも依存してしまうし、また他のSQLデータベースに持って行けるかというと非常に怪しい。

そこで、DBを刷新しよう、と言うことになった時を考えて欲しい。ストアドのロジックは使える部分も多いが、互換性を考えるとある程度は捨てる羽目になる。チューニングはやり直しである。ましてや例えばOracleからPostgreSQLにダウンサイジングする案件などの場合、完全移植である。確かにデータ構造は長生きである。しかし、データ構造を格納するRDBMSとそのプログラムは、実際には長生きではない。

また、再利用性は、単語が違う意味に化けている。通常OO言語における再利用性とは類似のプロジェクト同一言語で議論されるものである。それに対して、ここでいうExcel等でも再利用できるという話は、他のインターフェースから利用可能だという話になる。これは再利用性ではなく、相互運用性の話である。そして、相互運用性の話をするなら、ここでOO言語が対抗して出してくるのはSOAとなる。SOAで使われる標準化されたXMLベースのプロトコルは、現実として標準実装すらないSQLより遙かに相互運用性が高いといえないだろうか。

このような欠点は、1つのDBが中核にあって、OO言語を周辺のUIとしてのみ利用できるような場合には全く無視できるものである。いわゆる企業の内部システムか、中規模のWebサイトだ。90年代後半から2000年代前半にかけての中規模システムというのはだいたいこれでまかなえるレベルであり、その当時の経験から出た、といえよう。

では、逆に欠点が強く出るところはなんだろう。3つ考えられる。

最初に考えられるのは、超簡単なSQLしか使う必要のない、O/Rマッピングで十分な性能をあげられる場合だ。これは複雑なクエリを要求されるのことの多い業務システムでは滅多にないが、一方で単純な構成で性能を要求されるWebサイトのようなケースではままある。そもそも、昨今ではこれらの場合にRDBMSすら使わずKVSを多用する事が多いが、これらはその種のストアド機構など持たないため、自動的にたぶんOO言語で書くことになる。

次のは、複数種類のデータベースに対応しないといけないパッケージ商品だ。こういう商品でSQLをインターフェースにすると、ストアドでがちがちに固めた場合はともかく、通常のSQL文には過度のチューニングをさせられないことになる。ストアドにすると、言語側で記述すればそのまま対応できるロジック(再利用性は高い)が、今度は各DBごとにばらばらになり、個別実装にならざるを得なくなる。スピードが売りなら、それをするのもいいだろう。しかしビジネスロジックを例えばPostgreSQL,MSSQL,Oracleの3種類全部書くのは、果たして割に合うか。下手をするとバージョンごと、と言うことにもなりかねない。

最後はDBが1台で済まないケースだ。例えば1台で間に合わない性能を出さないといけないケースを考えよう。最近だとまず、memcachedを前段キャッシュに置くだろう。まずこれを置く場所に困る。SQLストアドの中に置けばいいだろうし、そう言うバインディングもある。しかし、O/Rマッピングのようなシンプルなクエリの場合、ちょうどSQLデータベースとの中間がきりのいい場所になる。このキャッシュ可能な場所の切り出しでは、全部のデータを一気に扱いたいSQLに部が悪い。

複数台無いとどうしようもない、いわゆる本当の大規模システムになった場合、SQL実装は分が悪い。例えば4ノードに拡大することを考えた場合、商用DBはどれも高価すぎる。オープンソースのものはいくつかあるが、多くは開発進行中であり、通常のSQLデータベースにはない制限、異なる性能特性に対応することを余儀なくされたりする。更新および検索の負荷分散機能も、SQLフロントエンドとして実装するのは大変である。このようなケースで相互運用性を求めるなら、中間層のサーバをもうけてXML-RPCベースなどのほうがまだいいだろう。

つらつらと書いてしまったが、RDBMSとそのフロントエンドでどう割り振るか、というのはシステムの根幹をなす部分であり、それだけに難しい。特に現在のデータベースはトランザクション処理系、データストア、プログラミング環境など、あらゆるシステムを網羅しているしろもので、それにいったいどれだけ依存するか、というのは一種の賭である。その賭を嫌ってSQLの機能を全く使わない、というむちゃくちゃな事をしているケースもたくさん見てきた。一方で、ストアド漬けになって、ベンダーロックインの状況から抜け出せない、あるいはバージョンアップの時に巨大プロジェクトになってしまって泣きを見ているケースも知っている(ただし、そう言うプロジェクトでは自分たちがベンダーロックインしていることが問題だと認識はしていないが)。

O/Rのインピーダンスミスマッチは古来からあちこちで摩擦を起こしている問題であり、我々はそう言う状況でもがき続けなければいけないのだ。そういう中で、確かに一般的ではあるが、あくまで一例にしかすぎないものをもって「これはこうすべきだ」と結論づけるのは、すくなくともL.starは拒否したい。ただ、もし強いて原則論を持ち出すとするなら、曖昧なものになってしまうが、以下のものをあげよう。

「データは転送するまでに可能な限り絞り込め」
異なるメモリ空間/マシン間でのデータ転送は非常にコストがかかる行為であり、できる限り避けた方が得である。その点、ある程度SELECT文の機能を活用する必要はあるだろう。

「SQLの特性に着目せよ」
OLAPとOLTPの話の例を出したが、SQLには特性の異なるものが多数含まれている。これらを一緒くたに議論をするとおかしな事になりかねない。

「アプリケーションが主なのか、DBが主なのか」
SQLはあくまでシステムの構成要素の一つであり、常に中心というわけではない。実際に中心はどれになるか、と言うのはちゃんと明確にしておく必要がある。