メッセージ。 - DBMSを使ったソフトウェア実装の定石について

# DBMSを使ったソフトウェア実装の定石について

先日、列車予約システムみたいなのを作るにあたって、プログラムの中でSQLをどう呼び出せばよいのか、実装の定石みたいなのがあるはず、と書いたことがあったのだけど(下記の記事)。

http://pikapika.to/~yf/momoka.cgi?op=readmsg&id=3007
http://pikapika.to/~yf/momoka.cgi?op=readmsg&id=3008

これに対して、以前お仕事でお世話になった@takekazuomiさんから詳細なコメントをいただきました。ありがとうございます!せっかくなので、情報共有のためこちらに転載させていただきました。

-- ここから

更新されていたのでコメントしようと
書いたのですが、終わった後でコメントが出来ないことに気が付き…
メールします。

もう解決しているでしょうが、思いついたことをコメントします。

「insertでの一意性保証方式だと、一意性が必要な要素ごとにテーブルを作らなければならなくて」
とありますが、現在のほとんどのRDBMSでは複合INDEXに(複数のカラムを結合して)UNIQ制約
を付けることができます。
つまり、列車番号(?)というカラムに、ひかり105号を入れて、予約番号とかのカラムに連番を
入れ、列車番号+予約番号でUNIQとするINDEXを作ると、「ひかり105号10番目」という行が1つ
しか作れないようになります。

これを使うと、「ひかり105号10番目」が取ってあっても、「ひかり106号の10番目は別途取れる」
という感じにできます。
「列車の何番目の購買」なのかを調べるのは、「count(*) from table where id <= got_id」で調べるの
が一番簡単な実装ですが、場合によってはパフォーマンスの問題が出るかもしれません。
その場合は、何番目の購買かをカウントするカラムを別途用意して、そこでカウントするという方法
が取られます。この方法は、予約と取消の両方でコードでカウンターをメンテンスしなければいけな
いのと、カウンターの行と、予約の行が別になるので、更新処理にトランザクションが必要になる
という問題があります。

このような問題があるのですが、今回のような要件では列車毎の予約情報テーブルと、座席の予約情報
のテーブルを1:Nの関係にして(header, detail という言い方をする)、予約情報に予約数(カウンター)
を保持し、追加、削除、更新はトランザクションで行うパターンがよく用いられると思います。
(どうして、header, detail パターンが使われるのが一般的かという説明が必要な気がしますが、
だいぶ長くなったので省略します。一言だけいうと、このパターンはRDBMSと相性が良いです)

説明がいまいちな気がしてぐぐってみたら、下記のURLが出てきましたが、これも今ひとつな気も
しますが、参考にはなります。(既読かもしれないけど、)
http://www.ogis-ri.co.jp/otc/hiroba/technical/JPLoP/DesignPatterns/HeaderDetail/HeaderDetail.html

今回のケースもそうでなんですが、RDBMSを使っていて、どうもピンと来ない場合があります。
個人的な意見ですが、SQLのクエリー部分は基本的に集合操作を前提として設計されているのに、
実業務に利用する場合の特に更新処置の部分が、集合操作的では無いのがギャップの原因の気が
してます。
このあたりは自分でも、もっと考えて見ないと分からない領域なんですが。

-- ここまで

@takekazuomiさん、本当にありがとうございます。やっぱり、プロの人の意見は信頼感があるなぁ。勉強になります。そういえば少し前、chatonのGauche部屋でも、「RDBMSの機能を使って大小関係の保証されたシリアルIDを振ること自体がRDBMSの思想に反している」というような意見がありました。この件と似ている気がします。考えると面白いところですね。

ただやっぱり、このへんの定石みたいなのは、ちゃんと本かなにか、分かりやすい説明にまとまってて欲しい気がするなぁ。
2011-03-22 22:13:15 / ふじさわ / Comment: 0 / Trackback: 0

Comment

コメント投稿機能は無効化されています。

Trackback

TrackBack投稿機能は無効化されています。