DBICでテーブル名切替の術
アプリを作ってると色々ログ系をDBに保存しておきたかったりするのですが、
ログテーブルって結構でかくなってしまう運命です。
DBによってはテーブルサイズがでかくなると検索効率が落ちてしまったり
ちょくちょく問題になってしまうのですが、
ログテーブルを年月ごととかで分割すると結構さくさく扱えたりします。
ただ、普通にDBIC使ってると分割したログテーブル毎にスキーマを用意する必要が
でてきてしまうです。
例えば
access_logってテーブルがあるとして、これを年月で分割して保存させるばやい、
access_log : Proj::Schema::AccessLog access_log_200706 : Proj::Schema::AccessLog200706 access_log_200707 : Proj::Schema::AccessLog200707 access_log_200708 : Proj::Schema::AccessLog200708
このようにテーブルに対応するスキーマを作る必要があります。
しかし
access_logとaccess_log_*は同じテーブル構造にしておくと、
Proj::Schema::AccessLogを一個つくれば他のaccess_log_*のテーブル用で
スキーマを作らなくてもよい方法があります。
普通にProj::Schema::AccessLogだけを作っておいて検索する時に
$self->model->source_registrations->{AccessLog}->name('access_log_200706'); my @logs = $self->model('AccessLog')->search->all;
こうするだけ。
source_registrations->{AccessLog}->nameがテーブル名に対応しているので、
そのテーブル名の部分を検索したいテーブル名に差し替えるだけで
差し替えたテーブル名を使って検索できます。
もちろんこれでInsertやUpdateなどもいけます。
ただ、これだとaccess_log_200706とaccess_log_200707をあわせて検索とかできないですが、
その場合はMERGEをつかってやればいいかと思います。
例えば、MERGEを使ってaccess_log_mergeというテーブルを作ってやって
source_registrations->{AccessLog}->name
にaccess_log_mergeを指定するとおk
実際にこういう形で運用してみて良い感じでやっておるます。
MERGEはやってませんが。
ちなみにうちの場合
access_logをベースのテーブルにしておいて
access_logと同じ構造のテーブルを必要になった時点で
CREATE TABLE IF NOT EXISTS $table_name LIKE access_log
と動的に生成してます
MySQL依存なSQLですけど。
こういう感じで動的テーブル生成することで、Cronでログを別テーブルに移したりとかしなくて良い感じです。