データベースには正規化というのがありのを知りました。極力可能な限り、無駄なデータは持たない、データの重複はさせないとのことですが、これはあくまで理論モデルで、現実には多少そこから外れても問題ないのでしょうか?例えば、フィールドに税抜きの価格があったとします。理論的にはこれを利用して、税込み価格を表示させるのが、教科書的な理想の正規化に則ったものだと思いますが、その値に1.05を掛けた値のフィールドを持たせてもそれ程パフォーマンスに影響はないような気がします。しかしながら、データベースの設計上はやはりそのようなことは避けるべきなのでしょうか?もしそうだとするとそこまでする理由がよく分からないのですが。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
私自身は次のような感じで考えてます。
●正規化
正規化では、システム全体のパフォーマンスや
例外処理などのことは一切考慮していない。
あくまで二重登録を避ける、とか、
1つ1つの表を「関係性のあるデータのみにまとめる」ためのもの。
設計の基本。
(基本はあくまでも基本。
「いかなる場合も死守せねばならないもの」ではない。
しかし、基本であるから、軽く扱っては絶対にいけない。)
マスタテーブル(顧客マスタ、商品マスタ、など)を
対象に(中心に)考えることが多いもの。
トランザクションテーブル(売上明細、業務日報、など)においても
もちろん、考慮されるべきものであるが、
トランザクションテーブルでは業務において正規化すると
パフォーマンス云々以前に、「単純に業務的に都合が悪くなること」は結構多い。
●パフォーマンス
基本的に正規化しまくった場合、リレーションの本数が増える。
RDBでは一般的にリレーションの本数が増えれば増えるほど、
正しい(というかパフォーマンス重視の)SQLを書かないと
クエリ(ビューなど)のパフォーマンスが落ちる可能性が高くなる。
※もちろん、パフォーマンスの低下にはその他の理由もたくさんあります。
●例外処理
業務のことをすべてカンペキにRDBシステム上で表現することが
難しい場合もある(けっこうある)。
そのような場合も含めていろんな例外処理があると思うが、
例外処理は正規化の枠をはみ出すこともある。
これはどうしようもないことも少なくない。
●例外処理以外に、トランザクションテーブルで正規化すると日常的に都合の悪いこと
日常的によくあるのが価格。
例えば売上明細のトランザクションテーブルでは
本来の意味の正規化から言えば、
商品IDさえ入力できるようにしてしまえば、商品の価格は入力しない。
でも価格は頻繁に変更されることがある。
このような場合に、正規化によって常にクエリ(SQL)で
商品価格を求める形にしてしまうと、
売価変更前の売上データまでもが、すべて、売価変更後の
価格にされてしまって、データベースが滅茶苦茶になってしまう。
また価格の場合、値引きなどもあり、そのときそのときで最終売価が違う。
このように、マスタの値が日常的に頻繁に変更されるフィールドに関しては
トランザクション側でも同じフィールドを持たせないとどうしようもない。
(厳密には、「定価」と「売価」はまったく性質が異なる、ということで
最初から「違うもの」として扱う、ということなのかもしれませんが)
取引先の締め日なども同様。
「この商品は今月送ったけれども、支払いの締め日としては再来月扱いにしてほしい」
などの要求は販売系では日常茶飯事でおきる。
このような場合も、「締め日」、などのフィールドは、マスタと
トランザクションの両方で持っておかないとどうしようもない。
でないと、業務の実情に合わないデータベースになってしまう。
以上のようなことをふまえ、バランスをとって
正規化を守ったり、崩していたりします。
パフォーマンスとメンテナンス、機能の製作期限などの面を見て、
くずしても問題ない場合のみ正規化を崩してます。
Accessの場合はストアドプロシージャが無いため、他のRDBソフトよりも
正規化を崩すケースが多いかもしれません。
ケースバイケースです。
No.4
- 回答日時:
先の皆様の回答とは別の切り口で書いてみます。
もし、税率変更を考慮した上で正規化してデザインすると、例えば以下の通りになります。
取引マスタ (取引番号, 取引日, 税引金額)
税率マスタ (適用開始日, 適用終了日, 税率)
そしてクエリは以下の通りになります。
SELECT
a.取引番号,
a.取引日,
a.税引金額,
b.税率,
TRUNC(a.税引金額*(1+b.税率),0) AS 税込金額
FROM 取引マスタ a
INNER JOIN 税率マスタ b ON a.取引日 BETWEEN b.適用開始日 AND b.適用終了日
レスポンスに問題がないのであれば、別に取引マスタに税込金額を追加する必要はありません。
上記をビューにして使えば済む話だからです。
ただ、上記では常に税率マスタを結合しなくては税込金額を得られませんから、これによりレスポンスへの影響が懸念される場合、税込金額をマスタに持たせることを検討します。「非正規化」と呼ぶことが多いです。
非正規化を行う場合、「税込金額の存在を知らない人もしくはアプリが税引金額のみを更新して不整合を引き起こしてしまう」リスクを回避しなくてはなりません。
DBMSにもよりますが、計算列(実体のない計算式による列)やトリガにより整合性を保持する仕組みを設けるのが一般的です。
正規化とはデータベース自身が整合性を維持するためのアプローチです。
したがって、上記の通り正規化してから非正規化項目の追加を検討する考え方をお勧めしておきます。
No.3
- 回答日時:
正規化自体をどう捉えるかが難しい。
というより曖昧です。例えば、顧客マスタがあり、顧客コード、顧客名があるとします。
伝票データには日付、金額と顧客情報を置く必要があるとしましょう。
普通に考えれば、「顧客情報として顧客コードを持てば良い。印刷時は
顧客マスタとJOINすれば顧客名は表示できる。」と考えるでしょう。
もし、「顧客コードと顧客名を持つ。」と答えたら「バカかお前は」と
言われるでしょう。確かに冗長ですね。
でも、必要な場合もあるのです。証券業務では証券を正しく表記する
必要があり、顧客が会社名を変えたりした場合でも改名前に発行した
証券はその名前で呼ばなければなりません。よって、マスタの単純
結合では改名前後のデータの顧客名部分を上手く表現できないのです。
税額については税率が変更された時を考えるなら、改正前と改正後では
税額が異なるのですから、価格と税額の両フィールドを持つことは冗長
ではなく、むしろ必須なのです。
こちらはもっと分かり易いですね。このように単純に割り切れない
問題を含むので、正規化といっても一律にどうこうではないのです。
あまり、「正規化」云々に拘泥される必要は無いと思います。
業務要件を考慮し、必要なフィールドは残し、不要なフィールドは
廃止するという自然な行為が、即ち「正規化」につながるのです。
No.2
- 回答日時:
正規化するかしないかはシステムの思想や性能などによります。
正規化をしないとどうなるかというと、無駄に同じデータを大量に持たせることになります。そうすると、データ変更の時に結構面倒になります(特にマスタデータといわれるもの)。ひとつのデータを変更しようとしても、どのテーブルに同一のデータがあるかわかなくなってしまったりするからです。
逆に正規化を教科書通り進めると、データの参照時にテーブルの結合が大量に発生してしまい、結果が返ってくるのが遅くなったりします。性能面で正規化しないほうが早くなることもあります。これを正規化くずしといいいます。
ただし、正規化崩しをするためにはまず、第3正規化まで進めてから性能などの問題が発生しそうな場合などのみ崩すということが必要です。そうしないとデータが色々なところにいってしまうので。
で今回の消費税の件ですが、個人的にはアプリで計算するべきだと思っています。なぜなら、法律が変わったら消費税率が5%から10%に変わったら、データベースへのパッチが必要になるからです。
ただ、そのデータが非常に少なく、データパッチを当てるのも簡単だというのであれば、必要ないかもしれません。
システムの規模、データ量などを考慮して決めると良いと思います。
No.1
- 回答日時:
SEです。
もうベテランの域だと思います。データベースの正規化は、データに整合性をもたせるためにもある程度はきちんとしておかなくてはいけません。
実際にシステムの構築に携わればわかりますが、データを更新するバッチプログラムでトラブルが発生したなどということは、日常的に発生します。
その際、正規化がきちんとできていれば修復する量は少なくて済みますが、同じデータがあちらこちらのテーブルに散在していた場合、復旧にはかなりの時間と、確認の手間がかかるわけです。
しかし、そうは言っても現実のシステムでは、やはり利便性との兼ね合いとなります。
質問者さんの例にあるように、売上のテーブルに税抜き価格と税込み価格の両方があるのは、当たり前です。
むしろ、お金の動きを正確に記録しておくために、両方の価格を別々のカラムにとっておくべきだと思います。
また、私の専門はBIやデータウェアハウスですが、これらのシステムの場合、検索速度を考慮して、むしろ積極的に正規化を崩すケースも存在します。
結論として、データベースの正規化は常に意識する必要があるが、実際にどれだけ適用するかはケースバイケースということです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(データベース) IT用語について質問です。 以前ITパスポートの試験を受けた際にデータベースが何の集まりかについての 2 2022/12/10 12:29
- その他(データベース) 業務用のデータベースサーバーの選び方について 4 2022/11/22 10:22
- 物理学 アインシュタインの質量とエネルギーの等価性(E=mc²)って間違ってますよね? 4 2023/01/14 13:29
- 宇宙科学・天文学・天気 AIが答えた方程式 1 2023/02/20 00:12
- 経済 税制についての素朴な疑問です。 現代における日本経済は停滞期であり、さらに超高齢社会にあります。 こ 4 2022/12/09 18:17
- 婚活 この男性どう思いますか? 男女問わずご意見頂けたら嬉しいです。 ○外見年齢 170cm 小太り(痩せ 12 2023/08/08 03:25
- 公認会計士・税理士 申告書等の税理士欄について 5 2022/09/14 17:23
- 弁護士・行政書士・司法書士・社会保険労務士 司法試験合格者の司法書士試験の受験について 3 2022/08/31 16:40
- Excel(エクセル) Excel ドロップダウンリスト(入力規則)に関してです データの入力規則で元データ79000行のド 3 2023/07/17 10:06
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Access レコードを追加できませ...
-
検索結果の列数を動的に変更したい
-
複数テーブルをひとつのテーブ...
-
AccessのInsertクエリのあとつ...
-
ACCESS 複数テーブル・複数フィ...
-
INSERT文で発行したオートナン...
-
検索フォームで検索するものが...
-
INDEXの無効化
-
データを削除しても表領域の使...
-
datapumpの実行方法について
-
CLOB型へのINSERT
-
postgreSQLのint型は桁数指定が...
-
Viewにインデックスは張れ...
-
ORA-00959: 表領域'****'は...
-
異なるスキーマからデータを抽...
-
他の処理でselectさせないよう...
-
count(1)とcount(*)の違い
-
Data Pump で大量データインポ...
-
create table時のINITIALとMAXE...
-
エクセルからアクセスにインポ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ACCESS 複数テーブル・複数フィ...
-
Access レコードを追加できませ...
-
検索結果の列数を動的に変更したい
-
【Access】外部結合を行う前に...
-
AccessのInsertクエリのあとつ...
-
INSERT文で発行したオートナン...
-
Accessで、マスター情報を参照...
-
複数あるAccessのテーブルを一...
-
AS/400のDBについて
-
ACCESSでの文字列の比較
-
データベースの正規化について
-
複数テーブルをひとつのテーブ...
-
Access2002 マスタテーブル変更...
-
データを削除しても表領域の使...
-
Viewにインデックスは張れ...
-
異なるスキーマからデータを抽...
-
CLOB型へのINSERT
-
datapumpの実行方法について
-
Data Pump で大量データインポ...
-
DELETE文でFROM句を省略した場合
おすすめ情報