Кэширование запросов

В больших и средних проектах, состоящих из большого количества модулей, компонентов, классов и библиотек, может возникнуть такая проблема, как вызов одинаковых запросов к mysql за один пробег скрипта. Другими словами, за все время выполнения скрипта один и тот же запрос может быть вызван несколько раз.
Так как большинство запросов – это запросы выборки SELECT, то такие действия явно будут лишними. В этой статье я расскажу, как это можно разрешить с помощью двух функций.

Очевидным решением этой проблемы является кэширование результатов запроса. Для реализации этого механизма нужно выполнить два условия:

  1. Все запросы должны проходить через одну функцию
  2. Выбираемые данные не должны меняться в процессе выполнения скрипта.

Ок, теперь для реализации этого простого механизма кэширования нам потребуются, по меньшей мере, две функции.

Первая функция будет выполнять сохранять запросы и результаты в кэш:

function cache_query($sql, $result) {
	global $qcache;
	$qcache[$sql] = $result;
	return true;
}

А вторая функция будет выполнять запросы к БД.

function db_getrow($sql) {
	global $qcache;
	if (empty($qcache[$sql])) {
	    $result = mysql_query($sql);
	    $row = mysql_fetch_assoc($result);
        } else {
	    $row = $qcache[$sql];
        }
        return $row;
}

Как видите, вторая функция, прежде чем выполнить запрос, проверяет – не кэширован ли уже запрос? Если он есть в кэше, то оттуда и берется, а запросов к БД не выполняется.

Преимуществом первой функции является инкапсуляция (сокрытие) механизма кэширования от программиста.

Другими словами, для реализации этого механизма, все запросы к БД просто надо будет пропускать через функцию db_getrow (если это запросы на выборку строки). Для реализации других выборок можно написать еще функций по аналогии с этой. И при использовании этих функций Вам уже не нужно будет заботиться о кэшировании запросов.

Есть правда еще один вариант, который подразумевает кэширование запросов на протяжении сессии, но с ним уже надо будет быть аккуратнее, чтобы поддерживать данные в актуальном состоянии.

Пример: Вы кэшировали запрос на выборку списка новостей при первом заходе посетителя на сайт. После того как он полазил по сайту минуты 2, новости могли добавиться, а он будет по-прежнему видеть старый список, актуальный на момент кэширования.

Принцип довольно простой, но в некоторых проектах может сократить кол-во запросов к БД почти в 2 раза 😉

Удачи.





Читайте также:



9 Ответов на “Кэширование запросов”

  1. Ожидал прочитать о библиотеках для кеширования. А оказалось совсем другое. :-(
    Надеюсь, никому в голову не прийдет использовать этот код у себя. Т.к. здесь нет ни управления временем кеширования, ни ограничения по памяти.

  2. > Т.к. здесь нет ни управления временем кеширования
    В статье я указал, что время действия кэша - один пробег скрипта. Т.к. используется он исключительно для решения проблемы повторяющихся запросов, то необходимости управлять временем нет.
    > , ни ограничения по памяти.
    Вот здесь уже согласен, зависит от конкретной задачи. Для большинства задач это будет не существенно, а там где делаются выборки очень больших объемов (статистические данные) неплохо было бы задуматься над архитектурой приложения 😉
    А про библиотеки для кэширования данных как-нибудь обязательно напишу :)

  3. Дык в mysql уже давно есть своё кеширование. Достаточно сделать кеш по-больше, и сервер не будет выполнять один и тот же запрос дважды. При этом сервер сам отслеживает актуальность данных.

  4. Хм. Интересно было бы проверить какой вариант быстрее будет работать :) Со встроенным кэшированием mysql или тот что средствами php здесь я сделал.

  5. Если в лоб сравнить кеш MySQL и этот PHP-код, думаю php может выиграть, т.к. в этом php-коде я не увидел проверки актуальности кеша. Поскольку речь идёт о серии запросов за одно выполнение скрипта, то вообще-то можно позволить себе не следить за актуальностью кеша.

    Но я так делать не буду ))

    Для меня важнее прозрачность и понятность кода.
    Если же в пределах одной страницы результат некоего запроса будет использоваться несколько раз - конечно же есть смысл сохранить его, но не в абстрактном кеше, а в нормальной смыслосодержащей переменной.

  6. Игорь

    Смысла в этиф функциях и их полезности не увидел. На стороне MySQL можно отлично реализовать кэширование, а на стороне пхп есть куча хороших либ с богатыми возможностями.

  7. Tar

    Вообщето хрень какая то. Как это два одинаковых запроса за один пробег скрипта?? Вы что?? Это баг черт меня побери. Если вы допускаете такое то зачем что то писать вообще?))

  8. cryptus

    [ссылка] это к вопросу о баге.. Функциональность программы не теряется если запрос выполнится два раза, поэтому это не баг это раз.
    Во-вторых архитектура веб-приложения может быть самой разнообразной и то что в некоторых из них допускают такие случаи как двойная выборка информации из бд для упрощения некоторых механизмов - это отнюдь не беда. Такие вещи легко исправляются либо мемкашем либо таким способом, какой описан в этой статье, за счет чего общая производительность системы увеличивается..

  9. Alexx

    Вроде просто считываем поля в массив, потом mysql_free_result, а с массивом работаем до конца скрипта, я правильно понял ?


© Copyright. . I-Novice. All Rights Reserved. Terms | Site Map