2012/07/25

[MySQL] テンポラリーテーブル&「INSERT ... ON DUPLICATE KEY UPDATE」構文

集計バッチで
MySQLのテンポラリーテーブルと
「INSERT ... ON DUPLICATE KEY UPDATE」構文の合わせ技を使ったので
メモ

まず テンポラリーテーブルを使うにあたって、MySQLのメモリ関係の設定値を確認する
参考) MySQLのメモリ関係のシステム変数 - 祈れ、そして働け ~ Ora et labora http://d.hatena.ne.jp/tetsuyai/20111006/1317873012


メモリ上に作成される テンポラリファイルは max_heap_table_size内まで
超えるとISAMテーブルとしてディスクに書き出されます。

(デフォ)max_heap_table_size グローバル 16MB

それから、今現在のDBのテーブルデータサイズから
テンポラリーテーブルのおよそのデータサイズを出す

参考)データベースとテーブルのサイズを確認する方法 - ふってもハレても
http://d.hatena.ne.jp/sho-yamasaki/20120405/1333640589
DB調べたら
Avg_row_length=151で、200としても
平均4万レコードくらいの データをテンポラリーテーブルにするから

200x4万レコード=800万byte → 7.63MB ・・・もんだいなすっぽ


で、
テンポラリーテーブルを使った 処理について

まず データの出力イメージは
商店Aテーブル、商店Bテーブル があります
それぞれの テーブルから 日付を絞って、商品番号でGroupByした集計を取得して、
それをマージします

↓こんな感じ
┌────┬───┬───┐
│商品番号│商店A │商店B │
├────┼───┼───┤
│   11111│     3│     2│
├────┼───┼───┤
│   11112│     0│     5│
├────┼───┼───┤
│   11113│     2│     0│
└────┴───┴───┘


まず 商店Aテーブルを集計して テンポラリーテーブルに データインサート

CREATE TEMPORARY TABLE `tmp_summary` (
  `商品番号` varchar(10) NOT NULL,
  `商店A購買数` int(11) NOT NULL DEFAULT 0,
  `商店B購買数` int(11) NOT NULL DEFAULT 0,
   PRIMARY KEY (`商品番号`)
)
  SELECT  商品番号 ,count(商品番号) as 商店A購買数, 0 as 商店B購買数
  FROM    商店Aテーブル
  WHERE   del_flg       =  0 
  AND     購買日   >= 'YYYY/MM/DD 00:00:00'
  AND     購買日   <= 'YYYY/MM/DD 23:59:59'
  GROUP BY 商品番号
  ;



SELECT文内の 「0 as 店舗B 購買数」のところは
次に集計する 店舗Bの購買数が入る部分を あらかじめ
0で埋めて先に作っとく的な感じ

次に 商店Bテーブルを集計して
先ほどのテンポラリーテーブル「tmp_summary」に マージしていきます
この時 「INSERT ... ON DUPLICATE KEY UPDATE」構文を使うと
MySQLが
既にPKが存在している時は UPDATE
なかったら INSERTしてくれます

INSERT INTO tmp_summary 
  SELECT  商品番号 , 0 as 商店A購買数, count(商品番号) as 商店B購買数
  FROM    商店Bテーブル
  WHERE   del_flg       =  0 
  AND     購買日   >= 'YYYY/MM/DD 00:00:00'
  AND     購買日   <= 'YYYY/MM/DD 23:59:59'
  GROUP BY 商品番号

  ON DUPLICATE KEY UPDATE
  商店A購買数=tmp_summary.商店A購買数+values(商店A購買数),
  商店B購買数=tmp_summary.商店B購買数+values(商店B購買数);


これで あとは テンポラリーテーブルをよしなに処理すればOK

select * from tmp_summary;

参考)
複合UNIQUEキーでも「INSERT ... ON DUPLICATE KEY UPDATE」構文は使える - 岩本隆史の日記帳
http://d.hatena.ne.jp/IwamotoTakashi/20080329/p1

テンポラリテーブルの作成MySQL|プログラムメモ
http://logic.moo.jp/memo.php/archive/11/

他のテーブルのデータを追加(INSERT ... SELECT文) - データの追加と削除 - MySQLの使い方
http://www.dbonline.jp/mysql/insert/index6.html