タグ:SQL

char(n)のnをアプリケーションから取得する - 象と戯れ - postgresqlグループ.
不慣れな入力系を作っているのですが、char(n)なカラムの最大長チェックを行う場合、どうやるのが一般的なんでしょうか。

attypemodを直接読み解く方法を使っているけど、あれは内部表現であって、外から使うのは本来ダメでしょう。ここはやはり正当にinformation schemaを使えばいいわけで。
yutaka=# create table test4(a char(1),b varchar(2),c varchar(6));
CREATE TABLE
yutaka=# select table_name,column_name,data_type,character_maximum_length from information_schema.columns where table_name='test4';
table_name | column_name |     data_type     | character_maximum_length
------------+-------------+-------------------+--------------------------
test4      | a           | character         |                        1
test4      | c           | character varying |                        6
test4      | b           | character varying |                        2
(3 rows)

とまあ、こんな感じに求まります。これなら標準なので、他のDBにも応用が利くわけで。

どこまで行っても標準が参考以上の役に立つことのなさそうなSQLで標準にそったところでどの程度の価値があるかは問わない方向で。

マルチコアの時代になれば、当然のごとく多重実行をいかにうまくやるか、というのがトレンドになってくる。しかしこれは非常に難しい。例えば、1995年の頃では、並列技術としては以下のような順序であっただろう。

  1. OSサポートの始まった最先端、マルチスレッド。n:m対応がかぎ。

  2. fork()によるマルチプロセス。オーバーヘッドも大きいので、prefork()

  3. 旧態依然とした非同期実行select()


しかし、これは時代とともに揺れ動いている。例えば、昨今のトレンドはもう違っていて

  1. C10K問題解決のための救世主、epollとかkqueueなどによる最先端非同期処理

  2. 成熟に向かっているマルチスレッド。ただし、n-m対応はカーネルレベルよりライブラリレベルが主。

  3. いまどきfork()


となって久しい。なにしろ最新の非同期技術は、ボトルネックをカーネルのソケット処理に押し込んでしまったので、もはやユーザレベルで出来るようなことはないに等しくなってしまった。

しかし、だ。最近出たGoogle chromeは、今時マルチプロセスモデルを採用する。他のブラウザが当然のようにマルチスレッドを使いこなすのに対して、だ。ブラウザのような場合は、性能面のオーバーヘッドはそれほどない。そして、プロセスが独立することによってサンドボックス化し、一部の影響を全体に及ぼさないようにしている。

そういえばIllustraがInformix Universal Serverになったときも、従来許されていたような関数がDataBlade内で使えなくなるなど、面倒な部分が目立ったものである。これもまた、マルチプロセスがマルチスレッドになることによる問題点である。おそらく性能面でプロセス<=スレッドなのはほぼ変わらないだろうが、使いやすさも考慮しないといけなくなりつつある。その点、おそらくRDBMS界隈では未だに旧態依然としたfork()を使っているPostgreSQLが有利なのだろうと思う。それがうまく生きるケースというのはなかなか見えてこないが。

おそらく商用のシステムなどの場合、OSのボトルネックの位置などを見越して、マルチスレッドとマルチプロセスの組み合わせなどということは頻繁にあるだろう。そのため組み合わせまで考慮し出すと大変なことになる。星の数ほどあるデザインの中で、適切なソリューションがなんなのかを考え続け、しかもその変化を見極めていかなければなぁ、とは思う。しかし、気を引き締めないと古い間違った意見にとらわれてしまいそうだ。

キャッチーなタイトルを付けるのは難しいな、と思いつつASTの"Linux is obsolete"をぱくって見る。

もうSQLと出会ってからすでに10年近くが経過している。非常に良くできたもので、知れば知るほど感心したものである。が、同時に業界の変化から取り残されていき、ダメになっているなと思われる部分もいっぱいある。ここに書かれているようなのは、もう昔から言われているようなことばかりだが、L.starなりに実体験をふまえてまとめてみた。


  • 論理構造しか記述できないこと




SQLは、論理的に以下にデータを取り出すか、と言うことに着目して記述する言語である。これはデータのやりとりの記述を実にシンプルにした、という利点がある。代わりに、実際の検索に必要な物理的な部分はプランナにより、自動的に最適化されるというのが売りである。この最適化が100%完璧に働くなら何の文句はない。実際にも、90%位はうまくいっていると言っていいだろう。

ところが、残り10%のうまくいかない部分が問題になる。それをなんとかするため、論理構造だけではなく、物理構造つまりSQL個別実装に特有の要素を加味して書かなければいけないということになる。しかも、標準SQLは、すでに相当複雑になっているにもかかわらず、個別実装に特有な部分を全て吸収できるほどの柔軟さを有していない。勢い、独自拡張に頼らざるを得ない部分が出てくる。これは文法的なSQLがどれだけ標準化によって統一されようとも、その奥にあるずっと実用的な側面は、OracleなりPostgreSQLなりDerbyなり何でも良いが、個別実装依存になることを意味する。

Joel on softwareのJoel氏は、「漏れのある抽象化の法則」という言い方でこれを説明している。リレーショナルモデルは完璧かもしれないが、SQLとその実装はその完璧さには及ぶべくもない。30年以上の並々ならぬ努力がこれを解決できていない。それどころが、どのくらいで解決できるかすら分からない。そのことからしても、問題の大きさはしれるだろう。はたして、これを解決するほどの労力は本当に必要なのだろうか。


  • 既存言語との致命的なミスマッチを抱え続けている




SQLと他の言語のマッピングほど、頭を悩まし続けている問題も少ないだろう。よく言われるのはO-R Mappingというオブジェクト指向言語とのマッピングだ。たくさんのフレームワークが内製商品OSS合わせて提案されている。L.starが知っているのは以下のようなものが挙げられる。

  • Pro*C,epcg,SQLjなどに挙げられる、SQL構文をソースコードに直接書き込めるもの

  • 昔のRoguewaveとかにあった、構文木を自作することで多数のDBに対応できるもの

  • iBATISのように、SQLテンプレートを用意し、それからオブジェクトを生成するようなもの

  • Hibernateのように、テーブル/オブジェクトを対応させて作るもの



いろいろあるが、正直決定版というものを見たことがない。いや、むろん実装として素晴らしいものも普及しているものもたくさんある。

しかし元々すりあわしづらいものを無理矢理くっつけるそのアプローチは、第三者視点から見ると醜悪である。L.starもJava屋としていろんなのを見たり書いたりしたことがある。が、はっきりOO側からこれは!と言うアプローチは見たことがない。逆に、SQL屋になってみて、しっくり来るアプローチも少ない。非常に大きなギャップを抱えているのだ。最近の挑戦はLINQだが、これもなんというかせっかくのC#言語の美しさを損ねている感がある。


  • OLAPとOLTPという、性能指標が異なる方式を統合しているなど、高機能すぎる




SQLデータベースの高機能さと言ったらない。例えばdbmのような単機能ハッシュだけなら、RDBMSよりずっと高速なハッシュDBはいくらでもあろう。また、大量データの解析のようなものの場合、RDBMSなど使わずにCSVとかを直読みするようなexecutor部分だけ引っ張ってきて書いた方が高速になる。しかし、この2つのアプローチの両方に対応でき、なおかつその中間のギャップを埋められるようなソリューションとして、SQLデータベースより普及しているものはない。これはSQL実装の美点の一つである。

しかし、欠点はすでに述べたとおり、あらゆるアプローチにおいてSQLが最良というわけでは決してないのだ。むしろ「SQLでできる」というがためにあらゆるものをキッチンシンク式に詰め込まれたアプリケーションはプログラムとしての自由意志よりもとにかくSQLを使うと言うところに主眼が置かれた実装である。それはもはやSQLに支配された奴隷という感すら受ける。例えば以下は個人的に「なんでこんなのにSQLデータベース使うの?」と思った例である

  • ログを格納するだけなら、検索しないのでログファイル+grepで十分ではないですか

  • 単なる銀行口座ならdbmで十分じゃないですか

  • 大規模解析はOLAP専用ツールに任せた方が高速じゃないですか


あと最悪なのはトランザクションである。もちろんbegin-commit(abort)で表せるトランザクションは、非常にありがたい便利なものである。しかし、それを実装することによる、性能面やロック競合などの部分はより物事を面倒にする。個人的にはこれらをサポートしない故に早いMyISAMを大変評価していたのだが。

このように、結構大きな問題が昔から知られている。今後もSQLは使われ続けるのだろうが、解決される見込みはどれもなさそうなものである。しかし逆に言うと、こういう部分をきっちり解決しつつ、より大きなスケールや性能を出せるアプローチは、今後普及を見込めるのでは無かろうか。個人的にはGoogleのMapReduce+BigTable、Apache Hadoop+HiveQLなどはそれに値する、非常に興味深いものだと思うのだが。

↑このページのトップヘ