Кешування даних

Кешування даних — це зберігання деякої змінної 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');

1. Залежність кешу

Крім встановлення терміну дії, кешовані дані також можуть стати недійсними відповідно з деякими змінами залежності (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 змінено.

2. Кешування запитів

У версію 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 максимальний розмір однієї одиниці даних дорівнює одному мегабайту. Тому, якщо розмір результату запита перевищить дане обмеження, то кешування не спрацює.

Be the first person to leave a comment

Please to leave your comment.