- PR -

テーブル設計(集計値はテーブルに持たせるのが良い?)

1
投稿者投稿内容
ax
常連さん
会議室デビュー日: 2004/04/07
投稿数: 34
お住まい・勤務地: 東京
投稿日時: 2005-01-05 20:15
現在、テーブル設計を行っており、以下ようなのテーブル(以下はサンプルです)
が存在します。よくあるような売上関係のテーブルです。
 ・売上(顧客ID,売上ID,日付)
 ・売上詳細(売上ID,詳細ID,商品ID,数量)
 ・商品(商品ID,価格)
ここで、一つの売上では複数の商品があり、その合計金額を計算する処理が
でてきます。毎回クエリで計算してもいいのですが、仮に売上テーブルにレコード
を作成する時に合計を計算し、合計のフィールドを設けて格納する、という設計
にしたほうがよいのか迷っています。
金額の集計は、顧客毎、売上毎、月毎に集計します。ユーザから集計用の画面にアクセス
があったタイミングで集計します(WEB系です)のでレスポンスが遅いと困るのですが、
毎回クエリで計算してもそれほど処理時間がかかるようなデータ量ではないと思っています。
一般的には、このような集計値はどのように設計するのがよいか、アドバイスお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2005-01-05 20:49
unibon です。こんにちわ。

引用:

axさんの書き込み (2005-01-05 20:15) より:
金額の集計は、顧客毎、売上毎、月毎に集計します。ユーザから集計用の画面にアクセス
があったタイミングで集計します(WEB系です)のでレスポンスが遅いと困るのですが、
毎回クエリで計算してもそれほど処理時間がかかるようなデータ量ではないと思っています。


提示されたテーブルだと、たとえば、「売上」ができた後に、それが参照している「商品」の「価格」が改訂(値上げ・値下げ)されると、集計結果も変わります。変わったほうが良い場合もなくはないと思いますが、普通は変わってほしくないことのほうが多いでしょう。
データ量や処理時間の検討ももちろん欠かせませんが、まずはこのような整合性の検討のほうが重要なのではないでしょうか。どっちが先、というよりも互いに絡み合った問題なのかもしれませんが。時間が絡むととたんに複雑になりますよね。
はにまる
ぬし
会議室デビュー日: 2003/12/19
投稿数: 969
お住まい・勤務地: 誤字脱字の国
投稿日時: 2005-01-06 00:33
集計結果をデータとして保持するという事は、システムにて状態管理の対象一つ増やすと言う事であり、システムの複雑化を招きます。
# この状態管理というのは「集計元の情報」と「集計結果の情報」の関係状態です。

そこのトレードオフを考慮されると良いでしょう。


例えば、2005年1月5日 00:00に集計処理で集計値を保持すると。その集計結果には「集計値の生成時間 2004/1/5 00:00」という情報が暗黙的に発生し、片一方の集計元にも「集計済時間 2004/1/5 00:00」という情報も暗黙的に発生します。そして集計処理後に集計元の情報を一方的に変更すると、この暗黙的な関連情報が崩れ状態が不整合になる訳です。

ただ、永続的に存在させる情報とは鮮度の問題を常に抱える為、他の情報と関連度合いが低い情報であるならば、鮮度(情報の整合性)は無視するというのも一つの手ではあります。

_________________
人生変わっちゃうかもよ?OFF会参加者募集中今考えるな、参加してから考えろ。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-01-06 00:42
引用:

axさんの書き込み (2005-01-05 20:15) より:
現在、テーブル設計を行っており、以下ようなのテーブル(以下はサンプルです)
が存在します。よくあるような売上関係のテーブルです。
 ・売上(顧客ID,売上ID,日付)
 ・売上詳細(売上ID,詳細ID,商品ID,数量)
 ・商品(商品ID,価格)
ここで、一つの売上では複数の商品があり、その合計金額を計算する処理が
でてきます。毎回クエリで計算してもいいのですが、仮に売上テーブルにレコード
を作成する時に合計を計算し、合計のフィールドを設けて格納する、という設計
にしたほうがよいのか迷っています。


結局のところトレードオフの関係になるので一般解は無いです。売り上げテーブルにレコードを作製するたびに計算すると言うことは、当然売り上げテーブルへレコードを作製する処理は遅くなると言うことです。しかも意図的に正規化LVを下げているのですから、整合性を維持するための保守コストも増加するでしょう。
キャッシュすると言う設計方法もあると思います。合計金額を計算したときの日時と、売り上げレコードをが更新された日時を保持しておき、必要に応じて再計算すると言う方法です。ロジックが複雑になる分、バグを誘発しやすいですし、毎回更新日時の照合を行うので、場合によっては遅くなりますね。
1

スキルアップ/キャリアアップ(JOB@IT)