symfony2のmariadbでのdoctrineスキーマ関連のコマンドが劇遅
doctrine:schema:update , doctrine:migrations:migrateのコマンドが恐ろしく遅かったので原因を調べました。
どうやら Doctrine\DBAL\Schema\AbstractSchemaManager の listTableForeignKeys 内で実行される information_schema.key_column_usage テーブルへの参照が恐ろしく遅い様子。mariaDBのバグ?それともMySQL時代からあるんだろうか。自分の環境では全DB内で1000以上のテーブルが存在しているので、おそらくそのせいか…
とりあえずカスタムドライバとカスタムスキーママネージャを作って対処することに。
Doctrine DBALカスタムドライバの作り方
こちらのリンク を参考にして作ってみます。
今回はCustomDoctrineというバンドルを作り、その中にドライバとスキーママネージャを作成します。
Driverクラス
<?php namespace CustomDoctrine\DBAL\Driver\CustomPdoMysql; use Doctrine\DBAL\Connection; use CustomDoctrine\DBAL\Schema\CustomMysqlSchemaManager; /** * PDO MySql driver. * * @since 2.0 */ class Driver extends \Doctrine\DBAL\Driver\PDOMySql\Driver { public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new CustomMysqlSchemaManager($conn); } }
SchemaManagerクラス
ここが肝心の処理部分。show create tableから取り出すことにしました。
<?php namespace CustomDoctrine\DBAL\Schema; use Doctrine\DBAL\Schema\MySqlSchemaManager; class CustomMysqlSchemaManager extends MySqlSchemaManager { public function listTableForeignKeys($table, $database = null) { if (is_null ( $database )) { $database = $this->_conn->getDatabase (); } $sql = "show create table {$table}"; $results = $this->_conn->fetchAll($sql); $tableForeignKeys = array(); foreach($results as $val) { $matches = array(); preg_match_all( "/CONSTRAINT `([^`]+)` FOREIGN KEY \(`([^`]+)`\) REFERENCES `([^`]+)` \(`([^`]+)`\)[\s]*(.*)/", $val['Create Table'], $matches); foreach($matches[0] as $key => $match) { $v = array(); $v['constraint_name'] = $matches[1][$key]; $v['column_name'] = $matches[2][$key]; $v['referenced_table_name'] = $matches[3][$key]; $v['referenced_column_name']= $matches[4][$key]; $v['delete_rule'] = null; $v['update_rule'] = null; $frules = explode("ON ", str_replace(",", "",$matches[5][$key]) ); foreach($frules as $rule) { $rule = preg_replace("/(.*)[\s]+$/", "$1", $rule); if(preg_match("/DELETE/", $rule)) { $v['delete_rule'] = str_replace("DELETE ", "", $rule); } if(preg_match("/UPDATE/", $rule)) { $v['update_rule'] = str_replace("UPDATE ", "", $rule); } } $tableForeignKeys[] = $v; } } print_r($tableForeignKeys); return $this->_getPortableTableForeignKeysList ( $tableForeignKeys ); } }
config.ymlの編集
app/config/config.yml 内を以下のように変更する。 driver_class 属性でDriverを指定すると、適用されるみたいです。
doctrine: dbal: driver: %database_driver% driver_class: CustomDoctrine\DBAL\Driver\CustomPdoMysql\Driver