開発環境で自動で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."&nbsp";
							$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で動かしてみた」