sheiko
Новичок
SQL кеширование в PHP
В проектах с высокой посещаемостью нередки проблемы связанные с производительностью сайта. Любой более-менее универсальный репозитарий контента подразумевает помимо таблиц структур данных раздельные таблицы для хранения данных различных типов. Соответственно уже для простейшей выборки списка документов потребуется связывать ряд таблиц, использовать группировку. В результате мы получаем на одну сполна начиненную сервисами страницу целый ряд «тяжелых» запросов. Число процессов на сервере базы данных растет пропорционально росту числа пользователей. Нагруженная база данных будет попросту складывать поступающие запросы в очередь, и выполнять их лишь по мере освобождения ресурсов. Таким образом, время генерации страницы может достигнуть шокирующих показателей – «Страница загружается. Откиньтесь на спинку кресла и отдохните потому, как это займет несколько минут».
Что же делать? В классическом подходе предлагается модифицировать архитектуру базы данных и сократить число SQL-запросов. Но это не всегда приемлемо. Можно попробовать сократить число переборов, выполняемых сервером базы данных для наших запросов. Для этого стоит воспользоваться командой MySQL EXPLAIN (http://dev.mysql.com/doc/refman/4.0/ru/explain.html), чтобы выявить неэффективные индексы таблиц. Не помогает? Тогда в ход идет тяжелая артиллерия: разнесение таблиц по разным базам, master/slave репликация, кластеризация (http://phpclub.ru/detail/download/2005/jun-jul/phpi13_2005.pdf). Однако такой подход может показаться клиенту не очень рентабельным. Давайте подумаем, что же можно сделать еще. А что если мы будем результаты наиболее тяжелых выборок читать не из базы данных, а из файлов? При тонкой настройке такое решение может оказаться вполне эффективным. Данный прием принято называть SQL-кешированием. В частности он достигается посредством функции CacheExecute популярного пакета API AdoDB (http://adodb.sf.net). С другой стороны чуть ли не в каждой статье посвященной AdoDB я встречаю нарекания к данной реализации SQL кеширования. Этот метод не подойдет и в том случае, если вы используете иной API абстрактных слоев баз данных. Например, API базы данных от PHPBB(http://phpbb.com).
Вся прелесть программирования в том, что если вас не устраивает что-либо в известных вам реализованных библиотеках, вы всегда можете написать свою собственную. Итак, давайте рассмотри пример библиотеки классов API SQL-кеширования на примере http://www.phpclasses.org/browse/package/2646.html. API должен позволить нам направлять в кеш-файл массив с результатами «тяжелых» запросов. Допустим «тяжелый» запрос выполняет метод getFetchListing, и его параметры содержание запроса и флаг, сообщающий выполнять SQL-кеширование или нет. При поступление SQL запроса метод проверяет наличие для него файла кеша. Имя файла с кешем результатов соответствует MD5 ключу содержания SQL запроса. Если файл найден, его содержание преобразуется в PHP массив и возвращается методом. Если файла нет, то выполняется запрос, а его результаты записываются в файл кеша. Но как же проконтролировать обновления в таблицах, задействованных в запросе? Для этого, перед тем как создать новый кеш-файл, мы анализируем SQL-запрос и формируем индексную таблицу в базе данных. Таблица содержит пары: MD5 ключ запроса, задействованная таблица. Соответственно если все SQL-запросы по модификации таблиц базы данных будут направляться нами в метод modify(), мы сможем определить модифицируемые таблицы и очистить кеш для них. Кеш-файлы будут автоматически вновь созданы, при следующем «тяжелом» запросы на выборку.
Таким образом, мы выносим результаты наиболее «тяжелых» запросов в файлы кеша, чем сможем существенно разгрузить многострадальную базу данных. Главное не перестараться с определением запросов в кеш, иначе придется ломать голову над тем как разгружать процессор сервера.
Если я кого-нибудь вдохновил на написание собственного API SQL-кеширования, могу посоветовать размещение блоков кеша SQL-запросов в разделяемой памяти сервера (http://www.php.net/shmop_open/, http://phpclub.ru/detail/article/2002-05-26), что существенно повысит производительность системы.
В проектах с высокой посещаемостью нередки проблемы связанные с производительностью сайта. Любой более-менее универсальный репозитарий контента подразумевает помимо таблиц структур данных раздельные таблицы для хранения данных различных типов. Соответственно уже для простейшей выборки списка документов потребуется связывать ряд таблиц, использовать группировку. В результате мы получаем на одну сполна начиненную сервисами страницу целый ряд «тяжелых» запросов. Число процессов на сервере базы данных растет пропорционально росту числа пользователей. Нагруженная база данных будет попросту складывать поступающие запросы в очередь, и выполнять их лишь по мере освобождения ресурсов. Таким образом, время генерации страницы может достигнуть шокирующих показателей – «Страница загружается. Откиньтесь на спинку кресла и отдохните потому, как это займет несколько минут».
Что же делать? В классическом подходе предлагается модифицировать архитектуру базы данных и сократить число SQL-запросов. Но это не всегда приемлемо. Можно попробовать сократить число переборов, выполняемых сервером базы данных для наших запросов. Для этого стоит воспользоваться командой MySQL EXPLAIN (http://dev.mysql.com/doc/refman/4.0/ru/explain.html), чтобы выявить неэффективные индексы таблиц. Не помогает? Тогда в ход идет тяжелая артиллерия: разнесение таблиц по разным базам, master/slave репликация, кластеризация (http://phpclub.ru/detail/download/2005/jun-jul/phpi13_2005.pdf). Однако такой подход может показаться клиенту не очень рентабельным. Давайте подумаем, что же можно сделать еще. А что если мы будем результаты наиболее тяжелых выборок читать не из базы данных, а из файлов? При тонкой настройке такое решение может оказаться вполне эффективным. Данный прием принято называть SQL-кешированием. В частности он достигается посредством функции CacheExecute популярного пакета API AdoDB (http://adodb.sf.net). С другой стороны чуть ли не в каждой статье посвященной AdoDB я встречаю нарекания к данной реализации SQL кеширования. Этот метод не подойдет и в том случае, если вы используете иной API абстрактных слоев баз данных. Например, API базы данных от PHPBB(http://phpbb.com).
Вся прелесть программирования в том, что если вас не устраивает что-либо в известных вам реализованных библиотеках, вы всегда можете написать свою собственную. Итак, давайте рассмотри пример библиотеки классов API SQL-кеширования на примере http://www.phpclasses.org/browse/package/2646.html. API должен позволить нам направлять в кеш-файл массив с результатами «тяжелых» запросов. Допустим «тяжелый» запрос выполняет метод getFetchListing, и его параметры содержание запроса и флаг, сообщающий выполнять SQL-кеширование или нет. При поступление SQL запроса метод проверяет наличие для него файла кеша. Имя файла с кешем результатов соответствует MD5 ключу содержания SQL запроса. Если файл найден, его содержание преобразуется в PHP массив и возвращается методом. Если файла нет, то выполняется запрос, а его результаты записываются в файл кеша. Но как же проконтролировать обновления в таблицах, задействованных в запросе? Для этого, перед тем как создать новый кеш-файл, мы анализируем SQL-запрос и формируем индексную таблицу в базе данных. Таблица содержит пары: MD5 ключ запроса, задействованная таблица. Соответственно если все SQL-запросы по модификации таблиц базы данных будут направляться нами в метод modify(), мы сможем определить модифицируемые таблицы и очистить кеш для них. Кеш-файлы будут автоматически вновь созданы, при следующем «тяжелом» запросы на выборку.
Таким образом, мы выносим результаты наиболее «тяжелых» запросов в файлы кеша, чем сможем существенно разгрузить многострадальную базу данных. Главное не перестараться с определением запросов в кеш, иначе придется ломать голову над тем как разгружать процессор сервера.
Если я кого-нибудь вдохновил на написание собственного API SQL-кеширования, могу посоветовать размещение блоков кеша SQL-запросов в разделяемой памяти сервера (http://www.php.net/shmop_open/, http://phpclub.ru/detail/article/2002-05-26), что существенно повысит производительность системы.
Вложения
-
23,1 KB Просмотры: 74