アプリ版:「スタンプのみでお礼する」機能のリリースについて

データベースには正規化というのがありのを知りました。極力可能な限り、無駄なデータは持たない、データの重複はさせないとのことですが、これはあくまで理論モデルで、現実には多少そこから外れても問題ないのでしょうか?例えば、フィールドに税抜きの価格があったとします。理論的にはこれを利用して、税込み価格を表示させるのが、教科書的な理想の正規化に則ったものだと思いますが、その値に1.05を掛けた値のフィールドを持たせてもそれ程パフォーマンスに影響はないような気がします。しかしながら、データベースの設計上はやはりそのようなことは避けるべきなのでしょうか?もしそうだとするとそこまでする理由がよく分からないのですが。

A 回答 (5件)

私自身は次のような感じで考えてます。



●正規化
  正規化では、システム全体のパフォーマンスや
  例外処理などのことは一切考慮していない。
  あくまで二重登録を避ける、とか、
  1つ1つの表を「関係性のあるデータのみにまとめる」ためのもの。
  設計の基本。
  (基本はあくまでも基本。
   「いかなる場合も死守せねばならないもの」ではない。
   しかし、基本であるから、軽く扱っては絶対にいけない。)
  マスタテーブル(顧客マスタ、商品マスタ、など)を
  対象に(中心に)考えることが多いもの。
  トランザクションテーブル(売上明細、業務日報、など)においても
  もちろん、考慮されるべきものであるが、
  トランザクションテーブルでは業務において正規化すると
  パフォーマンス云々以前に、「単純に業務的に都合が悪くなること」は結構多い。

●パフォーマンス
  基本的に正規化しまくった場合、リレーションの本数が増える。
  RDBでは一般的にリレーションの本数が増えれば増えるほど、
  正しい(というかパフォーマンス重視の)SQLを書かないと
  クエリ(ビューなど)のパフォーマンスが落ちる可能性が高くなる。

  ※もちろん、パフォーマンスの低下にはその他の理由もたくさんあります。
        
●例外処理
  業務のことをすべてカンペキにRDBシステム上で表現することが
  難しい場合もある(けっこうある)。
  そのような場合も含めていろんな例外処理があると思うが、
  例外処理は正規化の枠をはみ出すこともある。
  これはどうしようもないことも少なくない。

●例外処理以外に、トランザクションテーブルで正規化すると日常的に都合の悪いこと
  日常的によくあるのが価格。
  例えば売上明細のトランザクションテーブルでは
  本来の意味の正規化から言えば、
  商品IDさえ入力できるようにしてしまえば、商品の価格は入力しない。
  でも価格は頻繁に変更されることがある。
  このような場合に、正規化によって常にクエリ(SQL)で
  商品価格を求める形にしてしまうと、
  売価変更前の売上データまでもが、すべて、売価変更後の
  価格にされてしまって、データベースが滅茶苦茶になってしまう。
  また価格の場合、値引きなどもあり、そのときそのときで最終売価が違う。
  このように、マスタの値が日常的に頻繁に変更されるフィールドに関しては
  トランザクション側でも同じフィールドを持たせないとどうしようもない。
  (厳密には、「定価」と「売価」はまったく性質が異なる、ということで
   最初から「違うもの」として扱う、ということなのかもしれませんが)

  取引先の締め日なども同様。
  「この商品は今月送ったけれども、支払いの締め日としては再来月扱いにしてほしい」
  などの要求は販売系では日常茶飯事でおきる。
  このような場合も、「締め日」、などのフィールドは、マスタと
  トランザクションの両方で持っておかないとどうしようもない。
  でないと、業務の実情に合わないデータベースになってしまう。


以上のようなことをふまえ、バランスをとって
正規化を守ったり、崩していたりします。
パフォーマンスとメンテナンス、機能の製作期限などの面を見て、
くずしても問題ない場合のみ正規化を崩してます。
Accessの場合はストアドプロシージャが無いため、他のRDBソフトよりも
正規化を崩すケースが多いかもしれません。
ケースバイケースです。



  
  
    • good
    • 0
この回答へのお礼

ご丁寧に有難うございました。返答遅れてすみません。よく分かりましたる

お礼日時:2009/08/13 18:33

先の皆様の回答とは別の切り口で書いてみます。



もし、税率変更を考慮した上で正規化してデザインすると、例えば以下の通りになります。

取引マスタ (取引番号, 取引日, 税引金額)
税率マスタ (適用開始日, 適用終了日, 税率)

そしてクエリは以下の通りになります。
SELECT
a.取引番号,
a.取引日,
a.税引金額,
b.税率,
TRUNC(a.税引金額*(1+b.税率),0) AS 税込金額
FROM 取引マスタ a
INNER JOIN 税率マスタ b ON a.取引日 BETWEEN b.適用開始日 AND b.適用終了日

レスポンスに問題がないのであれば、別に取引マスタに税込金額を追加する必要はありません。
上記をビューにして使えば済む話だからです。

ただ、上記では常に税率マスタを結合しなくては税込金額を得られませんから、これによりレスポンスへの影響が懸念される場合、税込金額をマスタに持たせることを検討します。「非正規化」と呼ぶことが多いです。
非正規化を行う場合、「税込金額の存在を知らない人もしくはアプリが税引金額のみを更新して不整合を引き起こしてしまう」リスクを回避しなくてはなりません。
DBMSにもよりますが、計算列(実体のない計算式による列)やトリガにより整合性を保持する仕組みを設けるのが一般的です。

正規化とはデータベース自身が整合性を維持するためのアプローチです。
したがって、上記の通り正規化してから非正規化項目の追加を検討する考え方をお勧めしておきます。
    • good
    • 0
この回答へのお礼

ほんとうにご丁寧に有難うございます。私の様な初学者にはとてもありがたいです。勉強になりました。

お礼日時:2009/08/13 18:36

正規化自体をどう捉えるかが難しい。

というより曖昧です。
例えば、顧客マスタがあり、顧客コード、顧客名があるとします。
伝票データには日付、金額と顧客情報を置く必要があるとしましょう。
普通に考えれば、「顧客情報として顧客コードを持てば良い。印刷時は
顧客マスタとJOINすれば顧客名は表示できる。」と考えるでしょう。
もし、「顧客コードと顧客名を持つ。」と答えたら「バカかお前は」と
言われるでしょう。確かに冗長ですね。

でも、必要な場合もあるのです。証券業務では証券を正しく表記する
必要があり、顧客が会社名を変えたりした場合でも改名前に発行した
証券はその名前で呼ばなければなりません。よって、マスタの単純
結合では改名前後のデータの顧客名部分を上手く表現できないのです。

税額については税率が変更された時を考えるなら、改正前と改正後では
税額が異なるのですから、価格と税額の両フィールドを持つことは冗長
ではなく、むしろ必須なのです。
こちらはもっと分かり易いですね。このように単純に割り切れない
問題を含むので、正規化といっても一律にどうこうではないのです。

あまり、「正規化」云々に拘泥される必要は無いと思います。
業務要件を考慮し、必要なフィールドは残し、不要なフィールドは
廃止するという自然な行為が、即ち「正規化」につながるのです。
    • good
    • 0

正規化するかしないかはシステムの思想や性能などによります。



正規化をしないとどうなるかというと、無駄に同じデータを大量に持たせることになります。そうすると、データ変更の時に結構面倒になります(特にマスタデータといわれるもの)。ひとつのデータを変更しようとしても、どのテーブルに同一のデータがあるかわかなくなってしまったりするからです。

逆に正規化を教科書通り進めると、データの参照時にテーブルの結合が大量に発生してしまい、結果が返ってくるのが遅くなったりします。性能面で正規化しないほうが早くなることもあります。これを正規化くずしといいいます。
ただし、正規化崩しをするためにはまず、第3正規化まで進めてから性能などの問題が発生しそうな場合などのみ崩すということが必要です。そうしないとデータが色々なところにいってしまうので。

で今回の消費税の件ですが、個人的にはアプリで計算するべきだと思っています。なぜなら、法律が変わったら消費税率が5%から10%に変わったら、データベースへのパッチが必要になるからです。

ただ、そのデータが非常に少なく、データパッチを当てるのも簡単だというのであれば、必要ないかもしれません。

システムの規模、データ量などを考慮して決めると良いと思います。
    • good
    • 0
この回答へのお礼

早速の詳しいご回答有難うございます。とても分かり易かったです。大変参考になります。

お礼日時:2009/07/07 04:50

SEです。

もうベテランの域だと思います。

データベースの正規化は、データに整合性をもたせるためにもある程度はきちんとしておかなくてはいけません。
実際にシステムの構築に携わればわかりますが、データを更新するバッチプログラムでトラブルが発生したなどということは、日常的に発生します。

その際、正規化がきちんとできていれば修復する量は少なくて済みますが、同じデータがあちらこちらのテーブルに散在していた場合、復旧にはかなりの時間と、確認の手間がかかるわけです。

しかし、そうは言っても現実のシステムでは、やはり利便性との兼ね合いとなります。
質問者さんの例にあるように、売上のテーブルに税抜き価格と税込み価格の両方があるのは、当たり前です。
むしろ、お金の動きを正確に記録しておくために、両方の価格を別々のカラムにとっておくべきだと思います。

また、私の専門はBIやデータウェアハウスですが、これらのシステムの場合、検索速度を考慮して、むしろ積極的に正規化を崩すケースも存在します。

結論として、データベースの正規化は常に意識する必要があるが、実際にどれだけ適用するかはケースバイケースということです。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す