mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-06 16:16:53 +01:00
184 lines
14 KiB
Plaintext
184 lines
14 KiB
Plaintext
Кешування даних
|
||
===============
|
||
|
||
Кешування даних — це зберігання деякої змінної PHP в кеші та її отримання звідти. Для цієї мети базовий клас [CCache] компонента кешу має два найбільш використовуваних методи: [set()|CCache::set] та [get()|CCache::get].
|
||
|
||
Для кешування змінної `$value` ми вибираємо унікальний ідентифікатор (ID) і викликаємо метод [set()|CCache::set] для її збереження в кеші:
|
||
|
||
~~~
|
||
[php]
|
||
Yii::app()->cache->set($id, $value);
|
||
~~~
|
||
|
||
Дані будуть залишатися в кеші до тих пір, поки не будуть видалені із-за деяких умов функціонування кеша (наприклад, не залишилося місця для кешування, тоді більш старі дані видаляються). Для зміни такої поведінки ми можемо встановити значення терміну дії кешу при виклику методу [set()|CCache::set]. Тоді дані будуть видалені з кешу після певного періоду часу:
|
||
|
||
~~~
|
||
[php]
|
||
// зберігаємо значення змінної в кеші не більше 30 секунд
|
||
Yii::app()->cache->set($id, $value, 30);
|
||
~~~
|
||
|
||
Пізніше, коли нам знадобиться доступ до цієї змінної (у цьому ж або іншому запиті), ми викликаємо метод [get()|CCache::get] з ідентифікатором змінної. Якщо отримане значення - false, то змінна не доступна в кеші і ми повинні регенерувати її (оновити в кеші).
|
||
|
||
~~~
|
||
[php]
|
||
$value=Yii::app()->cache->get($id);
|
||
if($value===false)
|
||
{
|
||
// оновлюємо $value, тому що змінна не знайдена у кеші,
|
||
// і зберігаємо в кеш для подальшого використання:
|
||
Yii::app()->cache->set($id,$value);
|
||
}
|
||
~~~
|
||
|
||
При виборі ідентифікатора для кешованої змінної, враховуйте, що він повинен бути унікальним для кожної змінної з тих, що можуть бути кешованими у додатку. *НЕ* потрібно, щоб ідентифікатор був унікальним між різними додатками, тому що компонент кешу досить розумний для розрізнення ідентифікаторів різних додатків.
|
||
|
||
Деякі кеш-сховища, такі як MemCache, APC, підтримують завантаження декількох кешованих значень у пакетному режимі, що може зменшити накладні витрати на отримання даних, збережених в кеші. Метод [mget()|CCache::mget] дозволяє використовувати цю особливість. У випадку, коли кеш-сховище не підтримує цю функцію, [mget()|CCache::mget] буде як і раніше імітувати її.
|
||
|
||
Для видалення кешованого значення з кешу потрібно викликати метод [delete()|CCache::delete], а для очищення всього кешу - викликати метод [flush()|CCache::flush]. Потрібно бути обережним при виклику метода [flush()|CCache::flush], так як він також видаляє кешовані дані інших додатків.
|
||
|
||
> Tip|Підказка: клас [CCache] реалізує `ArrayAccess`,
|
||
> тому компонент кешу може використовуватися як масив. Нижче наведено приклади:
|
||
> ~~~
|
||
> [php]
|
||
> $cache=Yii::app()->cache;
|
||
> $cache['var1']=$value1; // еквівалентно $cache->set('var1',$value1);
|
||
> $value2=$cache['var2']; // еквівалентно $value2=$cache->get('var2');
|
||
> ~~~
|
||
|
||
Залежність кешу
|
||
---------------
|
||
|
||
Крім встановлення терміну дії, кешовані дані також можуть стати недійсними відповідно з деякими змінами залежності (dependency). Наприклад, якщо ми кешуємо вміст деякого файлу, і файл змінився, ми повинні прийняти кешовану копію як недійсну і зчитати свіжий вміст із файлу, а не з кешу.
|
||
|
||
Ми представляємо залежність як екземпляр класу [CCacheDependency] або класів, які його успадковують. Ми передаємо екземпляр залежності разом з кешованими даними, коли викликаємо метод [set()|CCache::set].
|
||
|
||
~~~
|
||
[php]
|
||
// значення дійсно не більше 30 секунд
|
||
// також, значення може стати недійсним раніше, якщо залежний файл змінено
|
||
Yii::app()->cache->set($id, $value, 30, new CFileCacheDependency('FileName'));
|
||
~~~
|
||
|
||
Тепер, якщо ми спробуємо одержати значення `$value` з кешу, викликавши метод [get()|CCache::get], залежність буде перевірена і, якщо вона змінилася, ми отримаємо значення false, що вказує, що дані потребують оновлення.
|
||
|
||
Нижче наведено перелік доступних залежностей кешу:
|
||
|
||
- [CFileCacheDependency]: залежність змінюється, якщо час модифікації файлу змінено;
|
||
|
||
- [CDirectoryCacheDependency]: залежність змінюється, якщо будь-який файл в каталозі або в підкаталогах змінений;
|
||
|
||
- [CDbCacheDependency]: залежність змінюється, якщо результат запиту деякого певного SQL виразу змінено;
|
||
|
||
- [CGlobalStateCacheDependency]: залежність змінюється, якщо значення певного глобального стану змінено. Глобальне стан — це змінна, яка є постійною в багаторазових запитах і сесіях програми. встановлюється методом [CApplication::setGlobalState()];
|
||
|
||
- [CChainedCacheDependency]: залежність змінюється, якщо будь-яка залежність ланцюжка змінена;
|
||
|
||
- [CExpressionDependency]: залежність змінюється, якщо результат певного виразу PHP змінено.
|
||
|
||
Кешування запитів
|
||
-----------------
|
||
|
||
У версію 1.1.7 Yii додана підтримка кешування запитів. Побудоване на кешуванні даних, кешування запитів зберігає результат запиту до бази даних в кеші і, тим самим, заощаджує час, що витрачається на одні й ті ж запити.
|
||
|
||
> Info|Інформація: Деякі СУБД, такі як [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html), підтримують кешування на стороні сервера бази даних. Підтримка кеша в Yii більш гнучка і потенційно більш ефективна.
|
||
|
||
### Увімкнення кешування запитів
|
||
|
||
Для того, щоб увімкнути кешування запитів, переконайтеся, що в [CDbConnection::queryCacheID] знаходиться ID підключеного компонента, що реалізує кешування. За замовчуванням це компонент `cache`.
|
||
|
||
### Використання кешування запитів з DAO
|
||
|
||
Для того, щоб використовувати кешування запитів необхідно викликати метод [CDbConnection::cache()].
|
||
|
||
Приклад:
|
||
|
||
~~~
|
||
[php]
|
||
$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](/doc/guide/database.ar). Для цього ми використовуємо метод [CActiveRecord::cache()]:
|
||
|
||
~~~
|
||
[php]
|
||
$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()` ще раз. Наприклад:
|
||
|
||
~~~
|
||
[php]
|
||
$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`, ми можемо закешувати кілька запитів, які виконуються підряд. У наступному прикладі ми кешуємо два запити:
|
||
|
||
~~~
|
||
[php]
|
||
// ...
|
||
$rows = Yii::app()->db->cache(1000, $dependency, 2)->createCommand($sql)->queryAll();
|
||
// буде використовуватися кешування запитів
|
||
$rows = Yii::app()->db->createCommand($sql)->queryAll();
|
||
~~~
|
||
|
||
Як відомо, при виконанні реляційного AR-запиту, можуть використовуватися кілька SQL запитів (це можна дізнатися, перевіривши [журнал повідомлень](/doc/guide/topics.logging)). Приміром, якщо відношення між `Post` і `Comment` `HAS_MANY`, то код, наведений нижче, виконає два запити:
|
||
|
||
- спочатку будуть обрані 20 записів;
|
||
- після цього будуть обрані коментарі для цих записів.
|
||
|
||
~~~
|
||
[php]
|
||
$posts = Post::model()->with('comments')->findAll(array(
|
||
'limit'=>20,
|
||
));
|
||
~~~
|
||
|
||
Якщо використовувати кешування запитів, як показано нижче, закешований буде тільки перший запит до БД:
|
||
|
||
~~~
|
||
[php]
|
||
$posts = Post::model()->cache(1000, $dependency)->with('comments')->findAll(array(
|
||
'limit'=>20,
|
||
));
|
||
~~~
|
||
|
||
Для того, щоб в кеш потрапили обидва запити, необхідно передати додатковий параметр, що задає кількість кешованих запитів:
|
||
|
||
~~~
|
||
[php]
|
||
$posts = Post::model()->cache(1000, $dependency, 2)->with('comments')->findAll(array(
|
||
'limit'=>20,
|
||
));
|
||
~~~
|
||
|
||
|
||
### Обмеження
|
||
|
||
Кешування запитів не працює з результатами, які містять посилання на ресурс. Приміром, вона повертається в деяких СУБД при використанні типу `BLOB`.
|
||
|
||
У деяких сховищах кешу є обмеження на розмір збережених даних. Приміром, в memcache максимальний розмір однієї одиниці даних дорівнює одному мегабайту. Тому, якщо розмір результату запита перевищить дане обмеження, то кешування не спрацює. |