プロファイリングについて #11
こんにちわ!nekokakです!
十一日目はDBIx::SkinnyでのSQLプロファイリングにつての考察です。
DBIx::Skinnyではsearch_by_sqlメソッドなどで複雑なSQLは生で書くことを推奨しています。
ORMの機能で複雑なhashrefをくみたてたり、
いろいろメソッドを呼び出して値を設定していく方法よりも、
生でSQLが書かれている方が可読性が上がるからです。
私はそう考えます。
ORMの利点としてはバックエンドのRDBMSを意識しなくていいというのがあげられますが、
ぶっちゃけそんなことたーどうでもいいです。
MySQLを使ってる人が急にポスグレでいくぜ!となって、
MySQL依存なクエリを生で書いてるから動かねーとかないですよね?
そんな酔っぱらいはどうでもいいです。
という冗談はさておき、search_by_sqlで生SQLを各場合は、クエリの最適化を行うのは用意ですね。
$db->search_by_sql('SELECT * FROM user');
と、SQLがみえてるので、ちゃちゃっとEXPLAINなどをかければいいと思います。
問題はormで生成したSQLをどのようにプロファイリングするかチューニングするかです。
まぁ、チューニングが必要なクエリはormで発行しないように。
で終わりでもいいんですが、1つの処理でどれだけのクエリが発行されるかのクエリ発行回数はみたかったりするでしょう。
またresultsetメソッドを使う場合なんかはインクリメンタルにクエリをくみたてるのであとで実際にどのようなクエリを実行したかをみたくなるでしょう。
DBIx::Skinnyでは発行したクエリを後から参照することができますので
その機能をつかうといいでしょう。
# 実験なので実際にファイルをつくらずメモリ上で試す
# DBコネクションの作成
my $db = Proj::DB->new({dsn => 'dbi:SQLite:'});
# 実験用テーブルを作成
$db->do(q{
create table user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
birth_on DATE
)
});
my $row = $db->create('user',{name => 'nekokak'});
$db->update('user',{name => 'yappo'}, {id => $row->id});
$row = $db->search('user', {name => 'yappo'})->first;
$row = $db->single('user', {id => 1});
$db->delete('user',{id =>1});
# query log を出力する
use Data::Dumper;
warn Dumper $db->profiler->{query_log};
このようなrun.plというプログラムがあるとします。これを、
SKINNY_PROFILE=1 perl ./run.pl
と実行するだけです。
すると以下のように出力されます。
$VAR1 = [
'create table user ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, birth_on DATE )',
'INSERT INTO user (`name`) VALUES (?) :binds nekokak',
'SELECT id, name, birth_on FROM user WHERE (id = ?) :binds 1',
'UPDATE user SET `name` = ? WHERE (id = ?) :binds yappo, 1',
'SELECT id, name, birth_on FROM user WHERE (name = ?) :binds yappo',
'SELECT id, name, birth_on FROM user WHERE (id = ?) LIMIT 1 :binds 1',
'DELETE FROM user WHERE (id = ?) :binds 1'
];
発行したSQLとbindした値が一緒にでます。
こうすればどのようなSQLを実際に実行したのかわかるようになるので、
無駄をさがしやすいですね!
明日はDBIx:Skinny::Mixinについてやろうとおもいます。
have a nice skinny days!:)