本で勉強したものと自分で個人的に経験したことのまとめ
Contents
- 1 値渡しと参照渡しの混同
- 2 型の制約が弱い
- 3 変更していいデータ、していけないデータ
- 4 参照系と履歴系のデータを区別する
- 5 リレーションでid(サロゲートキー)にするか否か
- 6 状態カラム
- 7 似たようなデータの点在
- 8 1テーブルのカラムを増やしすぎない
- 9 インデックスの貼り方が不適切(なさ過ぎて検索が遅い or 多すぎて更新が遅い)
- 10 物理削除なしなためサービス稼働後しばらくたってからのデータ爆発
- 11 性能テスト不備
- 12 型の不統一(特に日付と、数値)
- 13 トランザクションが小さすぎて落ちたときにデータ不整合がおこる
- 14 トランザクションが大きすぎて時間がかかりすぎる(一部落ちると最初から全部やり直し)
- 15 バッチ落ちたときの対処(落ちた場所からの再開が可能か、記録が正確にされているか)
- 16 全体的に異常時の設計に甘い
- 17 集計テーブルがないためにSQLが複雑になる
- 18 非正規化テーブルをアドホックに作ってしまう
- 19 関連テーブルを使わずに多列構造を取ってしまう
- 20 SQLが巨大すぎる(他の人が読めず、保守性が落ちる)
- 21 ループの中でSQLを発行させているため、遅い
- 22 nullと0,空白に対する意識の弱さ
- 23 安易なサロゲートキー(autoincrement型のid)
- 24 安易な削除フラグ
値渡しと参照渡しの混同
マスタ値が変更された場合、通常のテーブルの変更の影響をどの程度受けるかを考える。
型の制約が弱い
文字列数が異常に多かったり、not nullがあまりなかったりなど。緩すぎるといろいろと問題が起こる。特にnot null、一意制、外部キー制約、桁数には神経を配る
変更していいデータ、していけないデータ
参照されている側でどのように使われるか、変更した場合の影響度を考える。特にマスタ値の変更を気軽にできないようにする。過去のデータに影響を与える場合、履歴などを取る必要性もある。
参照系と履歴系のデータを区別する
伝票とマスタがあり、伝票に表示するデータに関して参照系(マスタが変わるとその値も変える必要があるか)か履歴系(その時の値をそのまま使い、マスタの変更があっても変化しない)をしっかり区別する
リレーションでid(サロゲートキー)にするか否か
通常のマスタのようなものはほぼサロゲートキーでOKだが状態に関するキー(例えば在庫など)は同一の意味を持つデータができる可能性があるものは状態を持ったキーでリレーションを考えるべき
状態カラム
ステータス系のカラムは注意しないと別々のものが混じることがあり。例えばステータスと削除を一緒にいれるなど。情報が同カテゴリーかを要注意する。またステータスの値に0をとらないようにする
似たようなデータの点在
簡単にテーブル同士の同期を考えない。その場しのぎのデータを作るのをやめる。意味があって似たようなデータが複数あるのはもちろん問題ない。
1テーブルのカラムを増やしすぎない
正規化されていれば原則として、1テーブルにするが、あまりにも量が多いときは別テーブルに分け、1:1型のテーブルにするのもあり。
インデックスの貼り方が不適切(なさ過ぎて検索が遅い or 多すぎて更新が遅い)
性能テストとからむが増えたデータでのパフォーマンスを想定すること。複雑なSQLはexplainで見ておくこと。プログラムではループの中でsqlを発行していないかを確認すること。一般にはリレーション系のキーではインデックスを貼ったほうが良い。
物理削除なしなためサービス稼働後しばらくたってからのデータ爆発
世の中のサービスを見ても永久にデータが保存できるサービスはない。量を考え、適切なところで削除する必要がある。
性能テスト不備
データが増えたときの実用的なパフォーマンスを考えているか。
型の不統一(特に日付と、数値)
日付がバラバラ。また数値の場合、小数点をどこまで許可するか、どのように表示するか。
トランザクションが小さすぎて落ちたときにデータ不整合がおこる
その処理が中途半端に終わった時に、不整合が起きていないか、再開できるのかを考える。
トランザクションが大きすぎて時間がかかりすぎる(一部落ちると最初から全部やり直し)
ワントランザクションが大きすぎると失敗した時に、時間的代償が大きすぎる。あまりにも大きすぎる処理は適度に分割させる。
バッチ落ちたときの対処(落ちた場所からの再開が可能か、記録が正確にされているか)
リトライする場合に、リトライができるようになっているか。記録(ログ)がわかりやすく吐かれているか。エラーを正常に返しているか。以前DBのコンバートのさいこれが甘かったため大変だった・・・
全体的に異常時の設計に甘い
例外処理全般の設計に関して。プログラムの部分であることが多いが・・・。特にレスポンスが悪いときのエラー画面など適切に出せないと実務でトラブルが起きやすい。
集計テーブルがないためにSQLが複雑になる
適切な集計テーブルがないためにSQLが巨大化していないか。
非正規化テーブルをアドホックに作ってしまう
主に集計情報を格納するためだが、リスクなどはわかって使っているか。主に参照だけのために使い、データをここに入れないほうがいい。
関連テーブルを使わずに多列構造を取ってしまう
これも完全にアウトではないが、関連テーブルを使わずにカラムに直で値を入れてしまう。簡便な分、変更がききにくい。増える上限が必ず限られているかの確証はあるのか
SQLが巨大すぎる(他の人が読めず、保守性が落ちる)
JOINなどが巨大すぎないか。4つ以上になった場合は別途わける工夫ができないか。
ループの中でSQLを発行させているため、遅い
集計できるものはいわゆるガツン系で取れないか
nullと0,空白に対する意識の弱さ
数字の場合、これらの区分けが適切か。特に日付(0000-00-00などと記録されることあり)、数字で影響度が大きく出てくる。この3つは厳密に分けること
安易なサロゲートキー(autoincrement型のid)
大体において、有益だがメリットとデメリットをわかっているか。関連テーブルでは不要なことが多い。
安易な削除フラグ
安易に論理削除をしていないか。論理削除はもちろんいいこともあるが、マイナス点もいろいろある。
データを見れるというメリットがある半面、データ量が増える(後々の検索できいてくる)、システムが複雑になる、where句で削除フラグ=0をいれないといけない、ステータスとの区別ができていないこともあるなどのデメリットもある