Кэширование запросов и результатов

Задача
Требуется исключить повторный запуск потенциально ресурсоемких запросов в базу данных, если их результаты не изменялись.

Решение
Используйте пакет PEAR Cache_DB. Он предоставляет в качестве оболочки уровня абстракции базы данных DB объект, который имеет схожие методы и автоматически кэширует результаты запросов SELECT:

require 'Cache/DB.php';
$cache = new Cache_DB;
$cache->connect('mysql://test:@localhost/test');
$sth = $cache->query("SELECT sign FROM zodiac WHERE element LIKE 'fire'");
while($row = $sth->fetchRow()) {
print $row['sign']."\n";
}

Обсуждение
Пакет Cache_DB используется почти так же, как и DB, но есть некоторые существенные отличия. Во-первых, требуется файл Cache/DB.php вместо DB.php. В этом случае файл Cache/DB.php загружает соответствующие классы DB. Вместо того чтобы посредством метода DB::connect() создавать спецификатор базы данных, с помощью оператора new создается объект Cache_DB, а затем вызывается метод connect() этого объекта.

Синтаксис метода $cache->connect() тот же самый, однако ему достаточно передать DSN, идентифицирующий базу данных.


Метод query() пакета Cache_DB работает точно так же, как и в DB, однако в Cache_DB нет методов prepare() и execute(). Метод query() возвращает спецификатор оператора, поддерживающего методы fetchRow() и fetchInto(), но режим выборки по умолчанию определяется константой DB_FETCH_ASSOC, а не DB_FETCH_ORDERED.Когда какой-либо оператор SELECT первый раз передается методу $cache>query(), то Cache_DB выполняет оператор и возвращает результаты точно так же, как и DB, но помимо этого он записывает результаты в файл, имя которого представляет собой хеш запроса. Если тот же самый оператор SELECT снова передается методу $cache->query(), то вместо того чтобы запрашивать базу данных, Cache_DB извлекает результаты из файла.

По умолчанию Cache_DB создает свои кэш-файлы в подкаталоге текущего каталога с именем db_query. Его можно изменить, передав имя каталога в составе массива параметров как второй аргумент конструктору Cache_DB. Следующий оператор определяет кэш-каталог как /tmp/db_query:

$cache = new Cache_DB('file',array('cache_dir' => '/tmp/'));

Первый аргумент, file, указывает Cache_DB, какой контейнер использовать для хранения кэшированных данных.


По умолчанию это значение file, но при этом необходимо указать еще и параметры контейнера во втором аргументе. Подходящим является cache_dir, указывающий Cache_DB, где создавать подкаталог db_query. Символ косой черты в
конце обязателен.

По умолчанию информация в кэше хранится в течение часа. Этим временем можно управлять, передавая другое значение (в секундах) при создании нового объекта Cache_DB. Ниже показано, как сохранить информацию в кэше в течение одного дня, или 86 400 секунд:

$cache = new Cache_DB('file',array('cache_dir' => '.',
'filename_prefix' => 'query_'),86400);

Время действия передается в третьем аргументе, поэтому необходимо также передать значения по умолчанию для первых двух аргументов. Содержимое кэша остается прежним, даже если база данных изменяется в результате запросов INSERT, UPDATE, или DELETE. Если в кэше хранится результат оператора SELECT, относящийся к данным, которых уже не существует в базе данных, то необходимо полностью очистить кэш непосредственно с помощью метода $cache->flush():

$cache->flush('db_cache');

Очень важно включить аргумент db_cache в вызов flush().


Кэш-система в PEAR поддерживает разделение кэшированных данных на различные группы, а объект Cache_DB помещает всю информацию, за которой он следит, в группу db_cache. Пропуск аргумента группы приведет к удалению файлов из базового каталога кэша (из которого, возможно, запускается ваш сценарий).

Файловый контейнер хранит каждый результат в файле с именем, основанным на MD5-хеше запроса, сгенерировавшего определенный результат. Поскольку MD5 чувствителен к регистру, то и файловый контейнер также чувствителен к регистру. Это означает, что если резуль-таты запроса SELECT * FROM zodiac находятся в кэше, а запускается запрос SELECT * from zodiac, то его результаты не будут найдены в кэше, и он будет запущен как новый запрос. Последовательное применение заглавных букв, пробелов и порядка полей при создании запроса приводит к более эффективному использованию кэша. Этот рецепт посвящен, в основном, файловому контейнеру, но кэшсистема в PEAR поддерживает множество других контейнеров, хранящих кэшированные данные, например, разделяемую память, PHPLib-сеансы, базы данных на основе библиотеки dbx и сеансы msession. Для
того чтобы использовать другой контейнер, надо при создании нового объекта Cache_DB передать соответствующее имя контейнера в качестве первого аргумента:

$cache = new Cache_DB('shm');

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Автоматическое присваивание уникальных значений идентификаторов
Выполнение запросов к базе данных SQL
Извлечение строк без цикла
Модификация данных в базе данных SQL
Определение количества строк, возвращенных запросом

Вернуться в раздел: PHP / 10. Доступ к базам данных