開発環境で自動でSQLにExplainをかけるコンポーネント
CakePHP 1.2.1を使ってます。
CakePHPはconfig/core.phpのdebug値を2にすると、画面にアクセスした際に発行されたSQL文が表示されます。これに加えて、発行したSQL文にExplainをかけてその結果を追加表示するコンポーネントを作りました。
動作チェックはMySQLでしましたが、explainを使えるPostgresなんかでも動くと思います。Oracleとかexplain planとかやらなきゃいけないっぽいので、たぶん動きません。
Explainの説明などは下記を参照(from opparaさんブログ)
http://dev.mysql.com/doc/refman/5.1/ja/explain.html
http://blog.livedoor.jp/nipotan/archives/3743275.html
http://dev.seesaa.net/article/238633.html
追記(2009/3/10)
不具合がいくつかあったのでバージョンアップしました。ソースコードなどは下記の記事を参照ください。
開発環境で自動でSQLにExplainをかけるコンポーネント バージョンアップ(1.0)
ソースコードはここからダウンロードするか、下記のソースコードをコピー&ペーストしてください。(ブログに載せているソースコードは古いので、ZIPファイルをダウンロードしてください)
app/controllers/components/explain_sql.phpという名前で下記を保存してください。
<?php class ExplainSqlComponent extends Object{ var $_controller; function startup(& $controller) { $this->_controller = $controller; } function showExplainSQL(){ if(Configure::read() < 2){ return ; } if( empty($this->_controller->modelNames) ){ return ; } $html_out = null; $modelname = $this->_controller->modelNames[0]; if( !empty($this->_controller->$modelname->getDataSource()->_queriesLog[0]) ){ $count = 0; $html_out .= '<table>'; foreach($this->_controller->$modelname->getDataSource()->_queriesLog as $key => $value){ //デバッグ時のDESCRIBEのSQL文は抜かす if( !preg_match( '/^DESCRIBE/', $value['query'] ) ){ $result = $this->_controller->$modelname->query("Explain ". $value['query']); $result[0][0]['query'] = $value['query']; //連想配列キーをテーブルのタイトルとして表示 if($count === 0){ $html_out .= '<tr>'; foreach( $result[0][0] as $titlekey => $titleval ){ $html_out .= '<th>'; $html_out .= $titlekey; $html_out .= '</th>'; } $html_out .= '</tr>'; $count++; } //内容表示 $html_out .= '<tr>'; foreach( $result[0][0] as $titlekey => $titleval ){ $html_out .= '<td style = "text-align: left">'; $html_out .= $titleval." "; $html_out .= '</td>'; } $html_out .= '</tr>'; } } $html_out .= '</table>'; $this->_controller->output .= $html_out; } } } ?>
それで、Explainをしたい画面のコントローラでコンポーネント指定して、afterFilterで呼び出してください。今回はすべての画面に強制的にExplainをかますためにapp_controller.phpに記載します
app/app_controller.php
<?php class AppController extends Controller { var $components = array('ExplainSql'); function afterFilter(){ parent::afterFilter(); $this->ExplainSql->showExplainSQL(); } } ?>
これをすると、下記の画面のように、Explainの結果が追加されます。
これで開発画面ですぐにインデックスの様子がチェックできる!!
_queriesLogにはSQL実行時間などが記録されているので、それを使ってn秒以上かかったSQL文のみExplainとかも簡単にできるよ!
追記(2009/5/16)
下記ブログで、CakePHP1.1でSQL Explain コンポーネントを動かす記事が書いてあります。ありがとうございます > coelacanthさん
眠るシーラカンスと新米プログラマー「CakePHPのexplainコンポーネントを1.1で動かしてみた」