SQL緊急救命室

第4回 スーパーソルジャー病~すべての問題をやみくもにコーディングで解くべからず

この記事を読むのに必要な時間:およそ 7 分

すべてをSQLで解くべきか

初級者よりも中級者がご用心

スーパーソルジャー病は,SQLに限らずプログラミング全般で発症します。その意味では,DBエンジニア以外の人にとっても本稿の教訓は適用できるものです。

この病気を特に発症しやすいステージが,初級者レベルを抜け出して,一通りのプログラミングができるようになったあたり,つまり中級者の入口ぐらいです。

このステージに達すると,自分がプログラミングでできることの幅も広がって,ちょっと難しい問題やひねりの効いた問題をプログラミングで解くのが楽しくなってくるころです。

それ自体はプログラマとしての成長と喜んでよいのですが,ともすると,難しい問題を難しいままの状態で解こうとしてしまう傾向につながります。本人にとってはパズルを解く楽しさがあるかもしれませんが,放っておくと無駄に複雑なプログラムができあがることになって,システム全体の観点では非効率で全体最適を損なう結果に陥りかねません。

データモデルを制す者はシステムを制す

本稿で見たように,特にデータベースにおいてはデータモデルのレベルで変更したほうがずっとシンプルかつ全体最適な解を達成できる問題は多くあります。こういうとき,テーブル構成に手をつけず,コーディングで何とかしようとするのは,無駄な労力を注ぎ込むのと同じです。

米国のプログラマであるEric Steven Raymondはエッセイ「伽藍とバザール」の中で,⁠賢いデータ構造と間抜けなコードのほうが,その逆よりずっとまし」注5という名言を吐きました。また,Frederick Phillips Brooks, Jr.も『人月の神話』「私にフローチャートだけを見せて,テーブルは見せないとしたら,私はずっと煙に巻かれたままになるだろう。逆にテーブルが見せてもらえるなら,フローチャートはたいてい必要なくなる。それだけで,みんな明白に分かってしまうからだ」注6と言いました。

2人に共通している認識は,データモデルがコードを決めるのであってその逆ではない,ということです。だから,間違ったデータモデルから出発してしまうと,その間違いをコーディングによって正すことはできないのです。コーディングに長けているだけでは,優れた戦術を駆使する兵士に過ぎません。コーディングは,あくまでシステムを作り上げる手段であって,目的ではありません。

注5)
伽藍とバザール山形浩生訳。レイモンドが念頭においているのはC言語ですが,この格言はすべての言語とデータに一般化できます。
注6)
『人月の神話 新組新装版』(滝沢徹,牧野祐子,富澤昇訳/ピアソン桐原/2010年)p.95

戦術より戦略

スーパーソルジャーって,格好いい印象があるじゃないですか。視野を狭くするのはいけないとわかってはいても,心理的な誘惑がありますね。

戦略的失敗を一人の戦術的活躍でひっくり返すスーパーソルジャーは,見た目の活躍が華々しいから映画やドラマでは好んで描かれるキャラクターよ。でも現実には,一人のソルジャーがどれだけ頑張ってもダメな設計を挽回することはできないわ。仮に奇跡的に一度はそれができたとしても,次のプロジェクトで同じ戦略上の失敗を繰り返して,不毛な戦いが継続されるだけ。

そうだ。我々が目指すべきは,スーパーソルジャーではなくスーパーエンジニアだ。その仕事は,戦略の失敗を挽回する戦術を探すことではない。正しい戦略を選択することだ。

……先生,やっぱり僕は,先生のような大人になってもいいと思いました。

……やっぱり今日のお前,気味悪いぞ。


(写真をポケットに押し込みながら)やあねえ。素直に感心しているだけよ。若い子って素直でいいじゃない。オホホホ。

【参考資料】
1.ミック WEB+DB PRESS Vol.62 連載「SQL緊急救命室」第1回「サブクエリ・パラノイア」
結合を使用したSQL文が抱える性能問題について解説しています。gihyo.jpでも公開しております。
2.Gerald Marvin Weinberg『スーパーエンジニアへの道』(木村泉訳/共立出版/1991年)
20年前に書かれた本ですが,スーパーエンジニアは「スーパーソルジャー」でも「スーパープログラマ」でもないという,時代を超えて通じる真実を教えてくれる本です。

データ同期の難しさ

複数のテーブルに保持されるデータの整合性を取るために,複数テーブルを更新する方法には何通りかのやり方があります。

「データの更新」の観点

まずは,⁠データ更新の同期を取るかどうか」という観点から,同期更新と非同期更新に分類できます。この両者の利点と欠点は,本稿でワイリーとロバートが話していたとおりです。データ間の整合性を完璧に保持するには同期処理を行うしかありませんが,パフォーマンスに悪影響を及ぼします。

非同期処理の場合は処理のスケジューリング自由度が高く,負荷の低いときにバッチ的に一括更新を行うことでシステム全体の負荷を下げられます。一方で,データ間にリアルタイムの整合性が求められる場合は,データ鮮度の落ちる非同期処理は向きません。また障害時にもデータ不整合の状態が長引くことになります。

「データの所在」の観点

もう一つの分類観点としては,データの所在があります。つまり,⁠データが同一のデータベースに保持されているか」⁠分散データベースに分かれて保持されているか」ということです。同一のデータベースに保持されている場合は特に問題ないのですが,分散データベース間のデータ更新は複雑です。

この場合も,同期処理と非同期処理に分けられますが,同期処理の場合は2相コミットのようなトランザクション制御や,Oracle DatabaseのDBLINKのような実装依存の機能を使うことになり,構築の難易度と性能リスクが増します。非同期処理の場合は,バッチによる一括更新やメッセージ連携のような方法が考えられますが,同一データベース内での更新に比べればやはり複雑になるのは避けられません。

こうしたデータ同期の方法論は,近年特に分散データベースの実用化が進んでいることから,非常に重要な分野になってきています。それだけエンジニアにとっても,難しい判断を要求される部分でもあります。

著者プロフィール

ミック

SI企業に勤務するDBエンジニア。主にデータウェアハウス業務に従事している。自身のサイト「リレーショナル・データベースの世界」でデータベースとSQLについての技術情報を公開している。『Web+DB Press』で「SQL緊急救命室」を連載中。

著書:『SQL ゼロからはじめるデータベース操作』(翔泳社,2010)『達人に学ぶ SQL徹底指南書』(翔泳社,2008)訳書:J.セルコ『SQLパズル 第2版』(翔泳社,2007)

Twitter:copinemickmack

SQL緊急救命室:サポートページ