MySQL: «умное кеширование»
Существует несколько видов кэширования данных при работе с БД. Этот топик посвящен так называемому «умному кэшированию»: в данном случае мы немного отойдем от идеи «берем из кэша: если в кэше нет, то берем из базы и кладем в кэш».
Сравнение данных в таблице БД и данных кэша будет производить по дате. То есть, если дата создания кэша отличается от даты последнего обновления таблицы на 1 день (неделю, месяц, год, …), то кэш необходимо обновить. Конечно, данный метод подходит, в основном, для тех таблиц, которые обновляются не часто (в разы реже, чем происходит обращение к ним). Перефразируя вышеупомянутую идею, получим: «проверяем кэш: если кэш устарел, то берем из базы и кладем в кэш».
Небольшая предыстория
Работая над проектом (веб-приложение) для внутренней сети организации, одной из задач была разработка интерфейса для заполнения сотрудниками собственного профиля. В том числе, пользователю необходимо было выбрать подразделение (отдел, управление). Вся структура организации хранилась в одной таблице, и чтобы вывести всё дерево структуры, необходимо использовать рекурсивные методы.
После внедрения системы планировалась большая посещаемость на первых этапах эксплуатации, поэтому каждый раз при редактировании профиля каждого пользователя (коих планировалось до 100-500 одновременно) нагружать сервер рекурсивной выборкой из БД слишком расточительно. С другой стороны, структура организации обновляется не так и часто, поэтому имеет смысл использовать кэширование.
Основной принцип
Как было сказано выше, основной принцип — проверяем кэш: если кэш устарел, то берем из базы и кладем в кэш. Но как узнать дату последнего обновления таблицы?
Для этого следует воспользоваться всего лишь одним SQL-запросом:
SHOW TABLE STATUS LIKE 'table'
, где table
, собственно, имя нужной таблицы.
Запрос возвращает значения следующих полей:
Name, Engine, Version, Row_format, Rows, Avg_row_length, Data_length, Max_data_length, Index_length, Data_free, AUTO_INCREMENT, Create_time, Update_time, Check_time, Collation, Checksum.
В нашем случае наибольший интерес вызывает значение поля Update_time, которое как раз и является датой последнего обновления таблицы (выполнения таких запросов, как INSERT
, UPDATE
, DELETE
). Формат значения: Y-m-d h:m:s
.
Теперь мы можем легко сравнивать дату последнего обновления и дату кэширования.
Простой пример
Для примера, рассмотрим такую простую программу.
// тот самый запрос $sql = "SHOW TABLE STATUS LIKE 'table' "; $query = mysql_query($sql); $array = mysql_fetch_array($query); $filename = "cache.htm"; $to_cache = true; // если файл кэша уже есть if (file_exists($filename)) { // достаем оттуда дату записи файла $file = file_get_contents($filename); $file = explode("[#upd]", $file); $file_datetime = $file[0]; $file_date = explode(" ", $file_datetime); // если дата кэша позднее обновления таблицы, // то нужный контент берем оттуда if ($file_date[0] > $array['Update_time']) { $content = $file[1]; $to_cache = false; } } // ксли файла кэша нет if (!file_exists($filename) || $to_cache) { // получаем содержимое таблицы $content = get_structure(); // в начало файла записываем дату и метку $cache_data = date("Y-m-d")."[#upd]".$content; file_put_contents($filename, $cache_data); }
В результате мы должны получить файл «cache.htm», вначале которого записана дата его создания/обновления в удобном для нас формате.
P.S. В качестве отношения сравнения дат кэша и обновления таблицы можно использовать нужную разницу дней.