- Начало
- Основы
- Работа с формами
- Работа с БД
- Кэширование
- Расширение Yii
- Тестирование
- Специальные темы
- Автоматическая генерация кода
- Управление URL
- Аутентификация и авторизация
- Темы оформления и скины
- Журналирование
- Обработка ошибок
- Веб-сервисы
- Интернационализация (I18N)
- Альтернативный язык шаблонов
- Консольные приложения
- Безопасность
- Улучшение производительности
- Генерация кода при помощи консоли (устаревшее)
Кэширование данных
Кэширование данных — это хранение некоторой переменной PHP в кэше и получение её оттуда. Для этой цели базовый класс CCache компонента кэша имеет два наиболее используемых метода: set() и get().
Для кэширования переменной $value мы выбираем уникальный идентификатор (ID)
и вызываем метод set() для её сохранения в кэше:
Yii::app()->cache->set($id, $value);
Данные будут оставаться в кэше до тех пор, пока не будут удалены из-за некоторых условий функционирования кэша (например, места для кэширования не осталось, тогда более старые данные удаляются). Для изменения такого поведения мы можем установить значения срока действия кэша при вызове метода set(). Тогда данные будут удалены из кэша после определенного периода времени:
// храним значение переменной в кэше не более 30 секунд Yii::app()->cache->set($id, $value, 30);
Позже, когда нам понадобится доступ к этой переменной (в этом же или другом запросе), мы вызываем метод get() с идентификатором переменной. Если возвращенное значение — false, то переменная не доступна в кэше и мы должны регенерировать ее (обновить в кэше).
$value=Yii::app()->cache->get($id); if($value===false) { // обновляем $value, т.к. переменная не найдена в кэше, // и сохраняем в кэш для дальнейшего использования: // Yii::app()->cache->set($id,$value); }
При выборе идентификатора для кэшируемой переменной, учитывайте, что он должен быть уникальным для каждой переменной из тех, что могут быть кэшированы в приложении. НЕ требуется, чтобы идентификатор был уникальным между разными приложениями, потому что компонент кэша достаточно умен для различения идентификаторов разных приложений.
Некоторые кэш-хранилища, такие как MemCache, APC, поддерживают загрузку нескольких кэшированных значений в пакетном режиме, которая может уменьшить накладные расходы на получение данных, сохраненных в кэше. Метод mget() позволяет использовать эту особенность. В случае, когда кэш-хранилище не поддерживает эту функцию, mget() будет по-прежнему имитировать ее.
Для удаления кэшированного значения из кэша надо вызвать метод delete(), а для очистки всего кэша — вызвать метод flush(). Надо быть осторожным при вызове метода flush(), т.к. он также удаляет кэшированные данные других приложений.
Подсказка: класс CCache реализует
ArrayAccess, поэтому компонент кэша может использоваться как массив. Ниже приведены примеры:$cache=Yii::app()->cache; $cache['var1']=$value1; // эквивалентно $cache->set('var1',$value1); $value2=$cache['var2']; // эквивалентно $value2=$cache->get('var2');
Зависимость кэша
Помимо установки срока действия, кэшируемые данные также могут стать недействительными в соответствии с некоторыми изменениями зависимости (dependency). Например, если мы кэшируем содержимое некоторого файла, и файл изменился, мы должны принять кэшированную копию как недействительную и считать свежее содержимое из файла, а не из кэша.
Мы представляем зависимость как экземпляр класса CCacheDependency или классов, его наследующих. Мы передаем экземпляр зависимости вместе с кэшируемыми данными, когда вызываем метод set().
// значение действительно не более 30 секунд // также, значение может стать недействительным раньше, если зависимый файл изменен Yii::app()->cache->set($id, $value, 30, new CFileCacheDependency('FileName'));
Теперь, если мы попытаемся получить значение $value из кэша, вызвав метод
get(), зависимость будет проверена и, если она изменилась, мы
получим значение false, показывающее, что данные требуют обновления.
Ниже приведен список доступных зависимостей кэша:
CFileCacheDependency: зависимость меняется, если время модификации файла изменено;
CDirectoryCacheDependency: зависимость меняется, если любой файл в каталоге или в подкаталогах изменен;
CDbCacheDependency: зависимость меняется, если результат запроса некоторого определенного SQL выражения изменен;
CGlobalStateCacheDependency: зависимость меняется, если значение определенного глобального состояния изменено. Глобальное состояние — это переменная, являющаяся постоянной в многократных запросах и сессиях приложения. Устанавливается методом CApplication::setGlobalState();
CChainedCacheDependency: зависимость меняется, если любая зависимость цепочки изменена;
CExpressionDependency: зависимость меняется, если результат определенного выражения PHP изменен.
Кэширование запросов
В версию 1.1.7 Yii добавлена поддержка кэширования запросов. Построенное на кэшировании данных, кэширование запросов хранит результат запроса к базе данных в кэше и, тем самым, экономит время, расходуемое на одни и те же запросы.
Информация: Некоторые СУБД, такие как MySQL, поддерживают кэширование на стороне сервера базы данных. Поддержка кэша в Yii более гибкая и потенциально более эффективная.
Включение кэширования запросов
Для того, чтобы включить кэширование запросов, убедитесь, что
в CDbConnection::queryCacheID находится ID подключенного компонента,
реализующего кэширование. По умолчанию это компонент cache.
Использование кэширования запросов с DAO
Для того, чтобы использовать кэширования запросов необходимо вызвать метод CDbConnection::cache().
Пример:
$sql = 'SELECT * FROM tbl_post LIMIT 20'; $dependency = new CDbCacheDependency('SELECT MAX(update_time) FROM tbl_post'); $rows = Yii::app()->db->cache(1000, $dependency)->createCommand($sql)->queryAll();
При выполнении приведённого кода, Yii сначала проверит, есть ли в кэше актуальный результат, соответствующий SQL-запросу, который мы собираемся выполнить. При этом проверяется:
- что в кэше есть данные с запросом в качестве индекса.
- что эти данные не устарели (прошло менее 1000 секунд с последней записи в кэш).
- что зависимость не изменилась (максимальное значение
update_timeто же, что было при сохранении результата запроса в кэш).
Если все три условия выполняются, то результат берётся из кэша. Иначе выполняется SQL запрос, его результат записывается в кэш и возвращается.
Использование кеширования запросов с ActiveRecord
Кэширования запросов также можно использовать с Active Record. Для этого мы используем метод CActiveRecord::cache():
$dependency = new CDbCacheDependency('SELECT MAX(update_time) FROM tbl_post'); $posts = Post::model()->cache(1000, $dependency)->findAll(); // реляционный запрос $posts = Post::model()->cache(1000, $dependency)->with('author')->findAll();
Метод cache() является короткой записью вызова CDbConnection::cache().
При выполнении SQL запроса, сгенерированного ActiveRecord, Yii попытается
использовать кэширования также, как это было описано в предыдущем подразделе.
Кэширование нескольких запросов
По умолчанию, каждый раз, когда мы вызываем метод cache() (как CDbConnection,
так и CActiveRecord), он кеширует следующий за его вызовом запрос. Все остальные
запросы НЕ кешируются пока мы не вызовем cache() ещё раз. К примеру:
$sql = 'SELECT * FROM tbl_post LIMIT 20'; $dependency = new CDbCacheDependency('SELECT MAX(update_time) FROM tbl_post'); $rows = Yii::app()->db->cache(1000, $dependency)->createCommand($sql)->queryAll(); // кэширование запроса НЕ используется $rows = Yii::app()->db->createCommand($sql)->queryAll();
Передавая методу cache() дополнительный параметр $queryCount, мы можем
закэшировать несколько выполняющихся подряд запросов. В следующем примере мы кэшируем
два запроса:
// ... $rows = Yii::app()->db->cache(1000, $dependency, 2)->createCommand($sql)->queryAll(); // будет использоваться кэширование запросов $rows = Yii::app()->db->createCommand($sql)->queryAll();
Как известно, при выполнении реляционного AR-запроса, могут использоваться
несколько SQL запросов (это можно узнать,
проверив журнал сообщений). К примеру, если
отношение между Post и Comment HAS_MANY, то код, приведённый ниже,
выполнит два запроса:
- сначала будут выбраны 20 записей;
- после этого будут выбраны комментарии для этих записей.
$posts = Post::model()->with('comments')->findAll(array( 'limit'=>20, ));
Если использовать кэширование запросов, как показано ниже, закэширован будет только первый запрос к БД:
$posts = Post::model()->cache(1000, $dependency)->with('comments')->findAll(array( 'limit'=>20, ));
Для того, чтобы в кэш попали оба запроса, необходимо передать дополнительный параметр, задающий количество кэшируемых запросов:
$posts = Post::model()->cache(1000, $dependency, 2)->with('comments')->findAll(array( 'limit'=>20, ));
Ограничения
Кэширование запросов не работает с результатами, содержащими ссылки на ресурс.
К примеру, она возвращается в некоторых СУБД при использовании типа BLOB.
В некоторых хранилищах кэша есть ограничение на размер хранимых данных. К примеру, в memcache максимальный размер одной единицы данных равен одному мегабайту. Поэтому, если размер результата запроса превысит данное ограничение, то кэширование не сработает.
