読者です 読者をやめる 読者になる 読者になる

生島さんが考える最強の言語 SQL

生島さんが誰と闘っているのか知らないけど、ちょっと気になることをつらつらと。

SQLは最も高級言語 - SQLer 生島勘富 の日記
SQLは最も高級言語2 - SQLer 生島勘富 の日記
SQLとはなんぞや? - SQLer 生島勘富 の日記

高級*言語*

どうも生島さんは、「SQL高級言語!」と言いつつ SQL の処理系 (RDBMS) のことを高級だと言っているようです。
言語が高級であることと、処理系の最適化が手厚いことをごちゃまぜにして、この言語高級!と言うのはまずいんじゃないでしょうか。別に、RDBMS を操作するための言語として SQL でなくたっていいのです。例えば Tutorial D/Industorial D もあるし、LINQ を SQL に変換せずに直接 DB の操作を行うような RDBMS/Linq to X と言うのも考えられます。


ここではとりあえず、言語としての SQL はそれほど高級ではないよ、ということを書きます。
SQL は、それなりに高級な言語だとは思います。でも、最も高級はどう考えても言い過ぎです。
ちょっと例を出してみましょう。
無効値 (ここでは -1) を計算結果に影響のない形に変換して計算したいとします*1

SELECT
    a * COALESCE(NULLIF(b, -1), 1)
FROM
    SomeTable
;

これを直感的とか喜べる人がいたらマジ尊敬ですわ。手続き的ではないことが高級さの証ではない、という例ですね。
さてさて、これをもっと汎用的なプログラミング言語で書いてみましょう。
Scala では、無効値を表すのに Option 型というものが使えます。使ってみましょう。

// Scalaの例。someListはList[(Int, Option[Int])]
someList map {
  case (a, Some(b)) => a * b
  case (a, _) => a
}

// もしくは1行で
//someList map { case(a, b) => a * b.getOrElse(1) }

SQL と比べて Scala の場合、NULL や無効値なんていう化物を相手にする必要がなく、Option が使えるので安心感が違います。
外面だけなら、COALESCE 関数や NULLIF 関数なんていう意味の分からない関数*2使わずに、CASE 式を使えば真似ることはできます。

SELECT
    a * CASE b WHEN -1 THEN 1
                       ELSE b
        END
FROM
    SomeTable
;

でもですね、この SQL を書いたとき、今まさにですけど、ELSE b とすべきところを ELSE a としちゃったんですよ。眠かったんです。
Scala 版ではどうでしょうか。

someList map {
  case (a, Some(b)) => a * b
  case (a, _) => b // このスコープにbなんて変数はないのでコンパイルエラー
}

・・・コンパイルエラーです*3
おっと思わぬミスで横道にそれました。ここで言いたかったことは、SQL では表面上真似ることはできても、元のコードよりも長いしこれこそまさに「COALESCE や NULLIF という標準関数を知らないレベル」に合わせている、とか思いませんか?
それに、無効値が入っている列とそうではない列をどう見分ければいいんでしょうか?システムハンガリアンを使うのはありかもしれませんね!あれ、なんて低級言語的発想をしているんでしょうか俺は。
それにそれに、無効値が入っているとか NULL が入っているということを忘れてしまい、

SELECT a * b FROM SomeTable;

としてしまうことだって可能なのです。
そしてほとんどのデータが正常な値の場合、こういったバグを見つけ出すのって難しいんですよねぇ・・・
その点 Scala 版では Option という型で守られているので、その値を取り出すには普通の Scala プログラマならパターンマッチとか使います。SQL では「無効な値が入ると決定しても、プログラマを守ってくれはしない」のに対して、Scala では「無効な値が入ると決定し、それを Option という型で表した瞬間からプログラマを守ってくれる」ということになりますね。
つまり、「常に None だった場合の処理を考える」ことを 型や API が強制してくれるのです。


このように、SQL は言うほど高級な言語と言うわけではないのです。
生島さんの主張を見てみましょう。

このように、人間が書いたソースから、データ(状況)に応じて違ったアルゴリズムを作り出しコンパイルしてくれる言語は、普及している言語の中ではSQLだけで、SQLは最も高級言語なのです。

SQLは最も高級言語2 - SQLer 生島勘富 の日記

見事に処理系と言語がごっちゃになっていますね。この主張は、「RDBMS が状況に応じて最適化してくれる」以上のことを言っていません。
RDBMS が高級 (この表現やだな・・・) だからといって、その上に乗っかっている言語が高級と言うことにはならないのです。

トレードオフ

言っていることはわからなくはないです。が、例えば「金ならいくらでもある。一番速いものを作ってくれ。」という状況があったとしてですね、すべてをアセンブリ言語で書けば解決するでしょうか?しませんよね。
もし作れたとしても、時間がかかりすぎて価値が提供できないということになる (提供できるまでの時間も価値である、ということ)。
そして実際には実用に耐えるものが出来上がることもないでしょう。「作れない」のです。
生島さんは「低級言語を使えば何でもできる」と考えているようですが、実際にはそうではありません。
複雑すぎるものを人間は扱うことができないのです。高級言語は確かに最初は楽をするための言語だったでしょう。
でも、今となっては違う。低級言語で人間が実現できないことを実現できるのです。


これを「スキルが足りない」と言うのは単なる根性論でしかなく、なんというか、その、人間を神だとでも思っているのですか?としか。
いやまぁどこからが人間にはできないのか、という線引きとなると、個人のスキル差という問題が出てくるのは認めます (明確に「ここ!」という線は引けない)。
ただ、人間を神と仮定して出てきた結論に意味はあるのか?と言うことです。ないです。

SQL を使わない方が生産性が上がる例外・・・?

外界とのやりとりを局所化して、依存性を下げるというのは、保守性の観点から見ても、テストのしやすさの観点から見てもいいことです。
これを例外と言うのは、その努力を放棄しようとしているとしか思えない。
これは生きている世界が違うということでしょう。

なぜ SQL ができたんでしょう

わかりません。
少なくとも、それを断言するだけの情報を持っていません。


まぁでもちょっと突いときましょう。

 「よし、アルゴリズムを書かずに、欲しいものを書くだけで結果が得られる言語を作ろう」
 「ユーザにも分かりやすくするために英語に近い表記を目指すぞ!」← これが最大の間違い(苦笑)
 「これをSEQUEL (Structured English Query Language)と名付けよう」
 という経緯で出来たものにトランザクションの一貫性など、主にエンタープライズ領域に特化した進化を遂げて、現在に至っています。

SQLとはなんぞや? - SQLer 生島勘富 の日記

「結構最初から一貫性は考慮されてたはず」
です。
E.F.Codd が 1969 年に出した論文ですけど、

  1. A Relational View of Data
  2. Some Linguistic Aspects
  3. Operations on Relations
  4. Expressible, Named, and Stored Relations
  5. Derivability, Redundancy, and Consistency
  6. Data Bank Control.

なっていたらしいです
C.J.Date が言うんだから論文持ってないけど信じましょう。
5 章のタイトルは「Derivability, Redundancy, and Consistency」とありますね。
Consistency は一貫性という意味です。


以下確証のない妄想です。

  • データこねくり回すのたるいよね
  • なんかいい感じにモデル化してみるお
  • お、いい感じ。名前付けよう → リレーショナル理論爆誕
  • これを操作するぼくのかんがえたさいきょうのげんごは・・・Alpha!
  • 実装チームも配備されたし実装だ!・・・あれれ、なんか思惑とは違う方向に・・・ → SEQUEL 爆誕

Wikipedia という確かなじょーほーすじから得た情報をもとに妄想したので、それなりに確かだと思うようん(投げやり


あとひとつ。今でこそルールベースのオプティマイザは絶滅しかけていますけど、生島さんはルールベースのオプティマイザ全盛期をどう考えているんでしょうか。気になります。
ちなみに俺はルールベースのオプティマイザ全盛期とか知らないので知りません。

SQL を使わないという選択肢

生島さんの言っているアルゴリズムは俺の思っているそれよりもはるかに狭い気がします。
なんかループがアルゴリズムだ!とかって言っているような感じもしないでもないですし・・・
いや、違うな。ジョインをアルゴリズムと呼んでいる・・・?


それは置いておきましょう。
SQL を使わないという選択肢は、十分アリでしょう。
だって SQL よりも高級な言語 (静的型付けの関数型言語とか) があるんですから。それは一番最初に示しましたよね。
ループとかアルゴリズムとかジョインとかはちょっと置いておきましょう。


型で手厚く守られた世界の人間からすると、生の SQL って怖いんですよねー。
SQL では整数とか文字列とか、かなり原始的な型を対象にして操作を行うので、そこらへんがじぇんじぇん高級じゃない。
関係ない id で JOIN しても動くんですよ?オソロシイ。
人間だもの、ミスくらいします。なのに奴らはそれを検知してくれない。
テスト不足?いやまぁそうなんですけど、RDBMS を使ったテストってどうしても「重い」んですよね。
動作が重いとかは置いといて、始めるまでにやたら準備が必要、という意味での「重い」。


生島さんがどこまでを SQL と呼んでいるのか気になりますが、なんか PL/SQL とか T-SQL という、「ストアドプロシージャ」を記述するための言語も含んでいるような気がします。
生島さんの言っている「アルゴリズム」がループとかジョインとかじゃなくて、いわゆる「アルゴリズム」だとして、それも DB 側に書け、という話なら現実的にはストアドプロシージャ使いますよね*4
PL/SQL は全然知らないけれど、T-SQL とか手続きも手続き、同じことばかり書かなきゃいけなくてもうね、って感じですよ。


ただこれはデータ操作に SQL なんて使うなよ、という話ではないです。
単に、SQL ってそんなに高級じゃないよね、あと 4GL ってもはや死語だよね、ということです *5
まぁ、アプリケーション書くときはできる限り SQL を薄くしたいし隠蔽したい、という考えの根っこはここらへんにあるわけですが。
「アプリケーション書くときは」と書いたように、アドホックな要求にこたえるためには SQL いいと思うんですよ*6。あとはデータウェアハウスとかそういう。
そういう SQL は大好きですし、便利です。でも、万能じゃない。
「鎚を持った者にはすべてが釘に見える」とはよく言ったものです。

SQL を広めたいのなら

SQL のいいところをどんどんアピールすればいいと思う。
SQL 可愛いよ SQL

*1:ここで NULL を使っていないのは、色々事情があるということで。普通にあり得ますよね?

*2:それにしても SQL の標準関数のネーミングセンスの無さはどうにかならないんですかねこれ。これだからベンダー独自の関数が使われちゃうんですよ

*3:え、間違えて _ としてしまえば一緒じゃないか?安心してください。_ は値を使わずに捨てる、という意味なので、_ を変数のように使うことはできません。もし間違えて _ としてしまったとしても、やっぱりコンパイルエラーです

*4:え?再帰 CTE?聞こえません

*5:そもそも関数型言語とか論理型言語って、なんとか GL の外にいませんか?

*6:D?聞こえません