私は、毎度毎度、「パワーオブパワー!増強最高!」でゴリ押ししています。
データベースにとっていいって何?な勢いで開発をしている昨今ですが、改めてデータベース設計について考えるタイミングありましたので、その時の所感をまとめておこうと思います。
- ユーザーがAまたBという回答をする
- 1日毎にA回答数を数えておきたかった
- 回答ユーザーは多く、秒間500ぐらいの回答数があった
- アクセスの“瞬間風速”で更新遅延がたまに起きていた
- 後日になって、Bの回答数も日別で欲しいといわれた
- ただし、Bの回答数の変化はリアルタイムで見る必要はない
というような状況があったとしましょう。
もともと、Aという回答を保管するためのカウントアップテーブルを作っておりました。
秒間アクセスが多くてアップアップしていた状況に、Bの回答も言われたので、テーブル改修が必要になったのです。
さあ、ここでどう改修しますか?
となるわけです。
この話題、先日、知り合いのエンジニアさんと話した折に聞いたことをもとにしております。
その時、実際に改修結果は「元のテーブルにB用のフィールドを追加した」でした。
その時、知り合いのエンジニアさんと一緒になって言ったのは
「いやーないわーないわー、それ、ないわー」
です。
いやー、だって
一つのテーブルに同時にみんなでゴリゴリupdateしにいっているテーブルに、さらに負荷をかけるようなことはしません、通常は。
しかし、一方でアプリ屋な私は「やりたい気持ちはわかる」というところでした。
何故かといえば、AとBの回答を1日毎に欲しいといわれたら、それはAとBの回答を1日毎に並べて表示したい、と言われる可能性が高い。だから1つのテーブル上にまとめて置いて、開発する時にもわかりやすくしておきたい。
という気持ちが無きにしもあらずだったからです。
アプリ開発、特にフロント回りも含めて開発していると、最終的にはユーザーに「見せる画面」をどう作るか?がどうしても一番、頭に残ります。
そういう時は、データベースの特性や発行SQLされる状態よりも、画面表示に必要なデータを以下に一度でもってこられるか、に頭が引っ張られがちです。
今回の話題に遭遇して、改めてデータベースにやさしい設計を、アプリ屋がするとしたら、
最初はアプリから見た「素敵な論理的テーブル設計」を作ったとしても、実際に動かした時の更新頻度などを考えた「堅牢な物理的テーブル設計」へ頭を切り替えることなのだろうなと思いました。
例えば、今回の改修を自分がするとしたら、最初はAとB一緒にしたいわーと3秒ぐらい思っていても、4秒後には「ただでさえデットロック怖いし、Bは後からでもいいのだから」ということで、RDBだけで行うとしたら、
- Bのカウントは別テーブル使って、1カウントで1レコードinsert
- Insertしたレコードを日別で集計して、B用のカウントアップテーブルへupdate
- 既存のテーブルとB用のカウントアップテーブルを両方見て画面表示
あたりでしょうか。特に既存テーブルをalterするのはコワイものなので(動いているテーブルを変更するのは勇気がいる。)、それなら素直に、画面表示する時に2テーブル見に行きます。だって、SQLが2回発行されたところで、秒間で行われるわけではないので。
最後に
データベース上でデータを直接見るわけではないので、データベース上に展開されているテーブルの構成が美しいかどうかに重きをおいても意味はありません。
いかに、そのデータが格納されたテーブルはどのような参照が行われ、更新頻度はどうなのか、アプリ全体の動きと使っているデータベースの特性をすり合わせる設計をすることが「やさしい設計」だろうな。
とつくづく思いました。