[Yii Framework] кеширование структуры БД через schemaCache

Автор: urmaul
09.12.2012 13:24

Yii Framework позволят очень просто делать сложные вещи. Например, для реализации ORM достаточно указать только имя таблицы. CActiveRecord сам распарсит структуру таблицы и сгенерит список аттрибутов.

За такую простоту приходится платить возросшим количеством запросов к БД. Это не страшно во время разработки, но в рабочем режиме вредные запросы вредны. Тем более, что в рабочем режиме, структура БД обычно не меняется.

Как раз для этих случаев струкуру БД можно кешировать. Причем, разработчики Yii сами рекомендуют это в документации.

Как включить кеширование

Для этого достаточно в конфиг БД добавить строчку:

 
'schemaCachingDuration' => 86400,
 

86400 - это время кеша в секундах. Можно указать любое другое число больше 0.

После этого страницы начинают грузиться на ~0.1с быстрее. Обычно это очень ощутимый прирост скорости.

Как проследить, что это работает

Запросы типа "SHOW CREATE TABLE ..." в логе БД продолжают отображаться, зато в логе событий должны появиться записи типа:

Serving "yii:dbschemamysql: ... " from cache

Противопоказания

Конечно, у кеширования есть недостатки. Если структура БД поменяется, ActiveRecord об этом не узнает пока кеш не устареет. А вы начнете встречаться с паранормальными ошибками типа "после обновления всё ломается, а потом само начинает работать на следующий день".

Можно, конечно, после каждого обновления вручную чистить кеш, но это не выход - рано или поздно кто-то об этом забудет.

Поэтому мы будем автоматически запускать очистку кеша после выполнения команды миграции.

Красивый способ сделать это - навесить на команду миграции behavior и чистить кеш при событии onAfterAction. Только, так не получится. Консольная команда - это вам не CApplicationComponent и через конфиг поведения на него не навесить. Придется наследовать. Да и само событие onAfterAction появилось в Yii только с версии 1.1.11. Короче, проще всунуть прямо в команду. У меня получилось что-то такое:

Конфиг console.php:

 
'commandMap' => array(
  'migrate' => array(
    'class' => 'application.commands.ChMigrateCommand',
  ),
),
 

Класс команды миграции:

 
Yii::import('system.cli.commands.MigrateCommand');
 
class ChMigrateCommand extends MigrateCommand
{
    public function run($args)
    {
        parent::run($args);
 
        $this->flushCache();
    }
 
    public function flushCache()
    {
        $db = $this->getDbConnection();
 
        if ($db->schemaCachingDuration > 0) {
            $cacher = Yii::app()->getComponent($db->schemaCacheID);
            if ($cacher)
                $cacher->flush();
        }
    }
}
 

Ещё одно. Метод flush() у CFileCache (по умолчанию используется именно он) всегда возвращает true, но не всегда он действительно срабатывает. Если у него нет прав на удаление файлов кеша - вы об этом не узнаете.

У меня процесс апача создает папку runtime/cache с правами 0766, хотя в коде кешера указано 0777. Не знаю, почему так. Но из-за этого "yiic migrate", запущенный не от юзера apache, не имеет прав удалять файлы кеша. Чтобы это обойти надо самому создать папку cache и вручную задать ей права 0777.

На этом всё. Пишите быстрые скрипты.

P.S.: Кстати, весь этот код уже добавлен в мой шаблон веб-приложения на Yii.

Обновлено 09.01.2013 11:56

 

Комментарии  

 
#1 Степан 29.11.2013 17:43
Спасибо за интересную статью. Очень помогла в работе.
Цитировать
 

Добавить комментарий


Защитный код
Обновить