Contents
正規化のデメリット
正規化についていろいろ書いてきましたが、メリットもあればデメリットもあります。
メリットとしては
- データの不整合が起きにくい
- 更新時の処理が速い
ことなどがあげられるでしょう。
逆にデメリットもあります。
それは「結合により検索系のSQLが遅くなること」です。
このため、わざと非正規化したテーブル設計をすることもあるようです。
一般論としては正規化の次数があがるほど、検索スピードは落ちる傾向にあるようです。
ただそうはいっても「データの不整合は絶対に防がなくてはいけないこと」から非正規化は最終手段と考えられているようですね。
この点は私の経験からも一致しますね。基本的に今までテーブルは正規化されたものが基本で、非正規化されたものというのはほとんど見たことがありませんでしたので。
更新速度を上げるためのポイントはいろいろとありますが、その1つがサマリーデータの格納です。
例えば受注テーブルと受注詳細テーブルがあったとし、受注テーブルのカラムが受注ID,注文日、注文者、受注詳細テーブルには受注ID、明細連番、商品名があったとします。
ここで商品の売り上げや個数を知りたい場合、基本的に受注テーブルに受注詳細テーブルをJOINして持ってきます。
ここでスピードのボトルネックが発生するわけですが、もし商品数という情報を受注テーブルに加えると
- 厳密な第三正規化ではなくなる
- 更新時における問題が起こる可能性がある(データの不整合が起きる可能性がある)
- 更新時の処理は逆に負荷がかかる
半面、
- 検索処理が非常に簡単でハイパフォーマンス
になります。
その他、日ごとの注文情報を出したいなどといったときには受注詳細に受注日をいれておくことで日ごとの一覧情報を出したい、となったときにも高速な検索処理を行うことができるのです。
このように正規化を崩すことでパフォーマンスを上げることは可能です。ただ、機械的にできるものではないことやデータの不整合が起こる可能性があるため、慎重に行う必要があります。
またデータベースの変更はプログラムの変更に比べて厄介なことが多いため、後戻りが簡単にできません。この点でも慎重に行う必要があります。
本日のSQL
n日前やn時間前を出すときにSQLでシンプルにできる方法を知りませんでした(汗)
例えば今の時間の3日前は下記のように簡単にできます。
1 |
SELECT CURRENT_TIMESTAMP - INTERVAL 3 DAYS; |
例えば1年以内の注文(order)を出したいといった場合、注文日(order_date)に下記のように検索条件を付けてあげればOKです。
1 |
SELECT order.* from order where order_date between CURRENT_TIMESTAMP - INTERVAL 1 YEAR AND CURRENT_TIMESTAMP; |