MySQLでマテリアライズドビュー4 実装編 手動更新(on demand)
さて、前回のMySQLでマテリアライズドビュー3 on commitのエントリーにてマテリアライズド・ビューの一般的な形は紹介しました。先の例は高速化という意味では成功でした。ですが、世の中何事も等価交換(トレードオフ)です。参照の高速化の見返りとして、ディスクの消耗という面で、オリジナルテーブル以上のディスク領域を消耗しています。また、commentテーブル追加時に都度トリガーを使ってマテリアライズ化したテーブルへも追加を行っているため、MySQLでのトリガーの低いパフォーマンスと相まって、更新時の負荷が重くなってしまいました。その差は以下のように無視出来ないレベルです。
- comment_materialized_insertトリガーがある場合
call insert_generate_series('comment(from_user_id,to_user_id,comment)','ceil(rand()*100000),ceil(rand()*100000),md5(?)',1,1000000,1);
Query OK, 0 rows affected (1 hour 5 min 11.74 sec)
- comment_materialized_insertトリガーがない場合
call insert_generate_series('comment(from_user_id,to_user_id,comment)','ceil(rand()*100000),ceil(rand()*100000),md5(?)',1,1000000,1);
Query OK, 0 rows affected (24 min 30.17 sec)
- トリガーを除去
DROP TRIGGER IF EXISTS `comment_materialized_insert`
- 差分を更新するinsert into select文を書く
INSERT INTO mv_comment SELECT comment_id , fu.user_id from_user_id , tu.user_id to_user_id , fu.user_name from_user_name , tu.user_name to_user_name , comment FROM `comment` cm,user fu,user tu WHERE fu.user_id=cm.from_user_id AND tu.user_id=cm.to_user_id AND comment_id > (SELECT MAX(comment_id) FROM mv_comment)
これを適時実行する。まとめて更新する分高速に動作する。例えば、参照前に上記SQLを実行するといった方法がon demandの使い方となる。
- ストアドプロシージャ化しておく
DROP PROCEDURE comment_materialized_insert; delimiter // CREATE PROCEDURE comment_materialized_insert() begin INSERT INTO mv_comment SELECT comment_id , fu.user_id from_user_id , tu.user_id to_user_id , fu.user_name from_user_name , tu.user_name to_user_name , comment FROM `comment` cm,user fu,user tu WHERE fu.user_id=cm.from_user_id AND tu.user_id=cm.to_user_id AND comment_id > (SELECT MAX(comment_id) FROM mv_comment) ; end; // delimiter ; call comment_materialized_insert();