tsucchi’s diary(元はてなダイアリー)

はてなダイアリー(d.hatena.ne.jp/tsucchi1022)から移行したものです

書評: 達人に学ぶDB設計徹底指南書

DB 設計の入門書です。初心者はもちろん、ある程度経験を積んだ人も自分の知識を整理するのに役にたつんじゃないかなー。*1

DB の本の場合、「理論」と「実践」のどちらかしか書いてないものが多かったりするのですが、この本は両方にふれて、かつトレードオフをきっちり説明しています。
また、「バッドノウハウ」や「グレーノウハウ」といったものにキチンとふれていて、さらに何故そういったものが生まれてしまうのかの説明とかもあって大変よかったです。

正誤表もあるのでみておくべし。っていうか、みんなよくこんなの見つけられるなー。(いくつか気づいたのもあったけど)

さて、基本的にはとても良い本で、超おすすめ(まだ読んでない人は、今すぐこの下のアフィ付きリンクからポチって GW 中に読むべし! :-)なのですが、「ちょっと違うよなー」と思ったところもいくつかあったので、それについて書きます。

RAID1 について

RAID1(ミラー)について、「性能は向上しない」とあるのですが、大抵のミラーは(ソフトでもハードでも)、読み込みは両面からやるので、読み出しは少し早くなります。

RAID1+0とかRAID6 とか

良く分かっていない初心者が対象なら、「RAID6+スペア」が一番良い構成だと思うので、RAID1+0 が本編で RAID6 が欄外、というのはちょっと納得ができません。5年前ならそれで良かったと思いますが。*2

参考: RAIDレベルの話: 1+0と6はどっちが安全か?

RAID5とか6とか

「書き込みは遅い」ってのはまあ事実なのですが、ハードウェアRAID なら大抵キャッシュバッテリーついているので、あまり気にならないはず。また、キャッシュが電池切れすると書き込みが超遅くなってビックリとか、WEB 系でも業務系でも「あるある」なハズなので、そこも触れてほしかったかも。

バックアップについて

フルバックアップについて、「サービス停止が必要」とあるのですが、Oracle ならアーカイブログモードなら稼働しててもフルバックアップ取れるし、MySQLInnoDB なら mysqldump に --single-transaction つけるとか、(使ったことないけど) xtrabackup 使うとか、DB のダンプコマンドと OS やディスク装置のスナップショット機能を組み合わせるとか、「サービス停止なし」で一貫性のあるフルバックアップを取る手段はあるので、これは「間違い」だと思います。

統計情報について

「統計情報は夜間にバッチで取られる」ので「重いから注意」的なことが書いてあるのですが、MySQLInnoDB だと更新時に自動で行われていて、しかもかなり軽い処理(らしい。実際気にしたことなかった)ので、あんまり気にしなくていいです。

参考: 大人のためのInnoDBテーブルとの正しい付き合い方。

単一参照テーブル

著者の造語で、コード定義のマスタとかを共通で持つやつです。これが「バッドノウハウ」として書かれているのですが、個人的には「グレーノウハウ」くらいだと思います。中規模以上のシステムだと、(コード定義以外の実績系とかマスタ系で)テーブル数が数百とかふつうなので、ここにコード定義が加わると下手するとテーブルが 1000 越えちゃいます。それが嫌な場合は(僕は嫌です)使っても良いのではないかなー、と思います。

ただ、これを使う場合、当該データにコード定義以上の意味が出現してしまった場合は、新しくマスタテーブルを起こす必要があります。僕のところではそういう変更は受け入れられていますが、こういったデータベースリファクタリング的なテーブル変更が受け入れられていない組織もあると思います。そういうところでは使わない方が良いと思います。

あと、Oracle だとキーに CHAR を使うと思われるので、そういう場合はキーの桁数拡張しにくくてダメってのはあると思いますが、MySQL の CHAR(あるいは VARCHAR 使ってもいいと思う)だとそういう心配は無いので、もう少し気軽に使える、というのもあります。*3

垂直分割

テーブルの列を分割するのが垂直分割なのですが、これがバッドノウハウとして紹介されています。僕はグレーノウハウ or セーフではないかな、と思っています。

たとえばあるキーに紐づくあたらしい画面が一個できたりすると、同一主キーに対する項目が数十個くらいできたりします。こういうときに、同じテーブルに項目追加するか、新しいテーブルを起こすかは難しい問題です。こういったケースで、新しいテーブルを起こしたり、あるいは既存のテーブルに項目追加したけど、「やっぱテーブルでかくてヤダから分けよう」とかなったら垂直分割だと思うのですが、これはセーフだと思います。

また、テーブルがでかすぎて、ALTER TABLE でやろうとすると停止時間中に終わらないから、やむなく新しいテーブルを起こすこともあったりします。これはグレーですね。

オートナンバリング

この本に書いてあるとおり、アプリでやるのは筋悪。シーケンスでもオートインクリメントでも DBMS でサポートしてるのなら好きなの使えばいいと思う。どうせたいがい片方しかサポートされてないので、標準の準拠とか割とどうでもいいんじゃないかなー。

列持ちと行持ち

僕は「タテ持ち」と「ヨコ持ち」とか言ったりしてますが、要は、項目が複数ある場合に、行とする(行持ち、タテ持ち)か、列とする(列持ち、ヨコ持ち)かの話です。

列持ちはグレーノウハウとしているのですが、僕はちょっと違うと思います。昔もDB のスキーマ設計とかの話(データの縦持ちについての項)に書いたのですが、実績系は列持ちすべきで、マスタは(要件に応じて)好きな方を使うべきかな、と思います。理由は前に書いたとおりで、実績系でたとえば 1000万件あるテーブルに、100項目行持ちすると、10億件に達してしまいちょっと運用が大変になるからです。

再度まとめ

「ちょっと違うなー」と思ったことをつらつら書きましたが、目次と比較してもらうと分かると思うのですが、本編と思われる DB の論理設計、物理設計の部分にはまったくケチがついてないことが分かるかと思います。そのくらい良い本だ、ということです。

まだ読んでない人は、今すぐこの下のアフィ付きリンクからポチって GW 中に読むべし! です。(大事なことなので2回言いました)

*1:少なくとも自分にとってはそうでした

*2:昔はソフト・ハードとも RAID6 は不安定な実装が結構あったため

*3:私は普段の業務で MySQL を使ってます