onemuri.space

RDB

事実の消失

例:EC サイト

  • 商品をカートに入れて発注するとカートテーブルに記録が残る
  • 売上テーブルの売上金額は設定テーブルの消費税率を下に計算する
  • 売上金額は発注した時点の消費税率を用いることとする
  • 2019 年内は消費税率 0.05
  • 2020 年からは消費税率 0.08

購入処理

2020/01/01 時点

【商品テーブル】

商品 ID 商品名 価格
1 失敗から学ぶ RDB の正しい歩きかた 2500
2 SQL アンチパターン 2000

【設定テーブル】

設定 ID 設定名
1 消費税率 0.08

【カートテーブル】

カート ID 売上 ID 商品 ID 個数 購入者
1 1 1 2 neko
2 1 2 1 neko
3 2 1 3 inu

【売上テーブル】

売上 ID 売上金額 売上日 配送状態
1 7350 2019-12-31 23:00:00 配送済
2 8100 2020-01-01 10:00:00 発注中

この時売上テーブルを見てみると、売上 ID が 1 の売上金額は 2019 年内の発注により消費税率 0.05 で計算されていて、売上 ID が 2 の売上金額は 2020 年からの税率 0.08 で計算されている

払い戻し処理

ここで、2020/01/02 に売上 ID が 1 のうち、カート ID が 1 の商品が1つ分返品された場合についての払い戻し処理について考えることとする

売上 ID が 1 について注目してテーブルの更新部分を見てみる

【商品テーブル】

商品 ID 商品名 価格
1 失敗から学ぶ RDB の正しい歩きかた 2500
2 SQL アンチパターン 2000

【設定テーブル】

設定 ID 設定名
1 消費税率 0.08

【カートテーブル】

カート ID 売上 ID 商品 ID 個数 購入者
1 1 1 1 neko
2 1 2 1 neko

【売上テーブル】

売上 ID 売上金額 売上日 配送状態
1 4860 2019-12-31 23:00:00 配送済

一見問題なさそうに思えるが、この売上金額 4166 は間違えている

なぜなら、消費税率は発注時点では 0.05 だったにもかかわらず、2020 年になってからの返品処理によって料金を再計算しようとすると 0.08 で計算しているからである

  • 2020 年内での計算
現在の売上テーブルの計算
(2500 + 2000) x 0.08 = 4860

払い戻し金額
7350 - 4860 = 2490
  • 2019 年内用の税率で計算
正しい計算は以下である
(2500 + 2000) x 0.05 = 4725

払い戻し金額
7350 - 4725 = 2625

実際のところ、消費税率 0.05 の時点で商品 ID が 1 の 2500 円の小計は 2625 円なので 2020 年内の計算が間違っていることがわかりますね

問題は何だったのか

消費税率の変更による払い戻し処理と、それ以外の問題点についても指摘する

  • 消費税率の履歴が全くわからない
  • 消費税率の作成日、更新日が分からないことで原因特定が難しい(見かけ上は消費税率は 0.08 で計算も間違っていないように思えるため)
  • 売上テーブルの配送状態は 発注中→キャンセル→再発注→配送済み のようになっていることが想定されるが、テーブル上では履歴が失われてしまう
  • カートテーブルの購入者が直書きされていて、もし名前を変更した場合にカート上の名称が誰なのかわかりにくくなる

どうすれば良かったのか

  • 設定テーブルに失効日を追加する
  • 売上テーブルに消費税率を追加する
  • 売上テーブルに配送状態が変わるごとにカラムを追加して、最新のものを有効であるとする

ただしデメリットも存在する

  • 履歴保存のためにカラム追加や行を追加する仕様にするとテーブルサイズが増えてしまう
  • テーブルサイズが肥大化した時に検索速度が劣化する(単純な主キーによる検索でなくなるため)

参考

失敗から学ぶ RDB の正しい歩き方

自己紹介用画像

Riki Akagi

2019年からDeNAで働いています。GCP(CloudSQL・GAE・Cloud Function etc)とGoでAPI開発に勤んでいます。睡眠やエンジニアリングに関することに興味を持って過ごしているのでその情報を皆さんに共有していけたらなと思っています。

自己紹介の詳細