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

F.A.Q. по трекеру и его настройкам
 • Просмотры: 1026
Аватара пользователя
PPK
Администратор
Благодарил (а): 82 раза
Поблагодарили: 1621 раз
Сообщения: 10284
Зарегистрирован: 21 мар 2009, 17:13
Сообщение

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

04 ноя 2013, 12:52

Думаю некоторые знают, что в phpBB3 есть встроенная возможность кеширования sql запросов (кроме подключения специальных php-модулей для кеширования), например, если обычный sql запрос выглядит так:

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE  post_id=12";
$db->sql_query($sql);
запрос с кешированием будет выглядеть так:

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE  post_id=12";
$db->sql_query($sql, 600);
600 - в данном случае, это время кеширования в секундах, если первый запрос будет выполняться при каждом выводе страницы, второй запрос при выводе страницы будет закеширован, будет создана md5 сумма sql запроса и в директории cache будет сохранён соотв. файл с данными этого запроса, при повторном запросе, если файл существует и время кеширования ещё не истекло, сам sql запрос выполнен не будет, и все данные будут взяты из сохранённого файла.

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

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE post_time>".(time()-3600);
$db->sql_query($sql, 600);
в конечном виде sql запрос будет иметь примерно такой вид

Код: Выделить всё

SELECT * FROM phpbb_posts WHERE post_time >1383546951
через какое то время

Код: Выделить всё

SELECT * FROM phpbb_posts WHERE post_time>1383547096 
и

Код: Выделить всё

SELECT * FROM phpbb_posts WHERE post_time>1383547128 
и т.д., т.е. при каждом выводе страницы, дата "последнего часа" относительно текущего времени будет меняться и каждый раз в кеше будет сохранятся новый sql запрос который никогда повторно использоваться не будет, за исключением случая одновременного (в одну секунду) запроса и вывода страницы, в результате получится большое количество бесполезных кешированных файлов и никакого эффекта от кеширования не будет.

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

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE post_time>".(time()-3600);
$db->sql_query($sql, 600, 'last_hour_posts');
last_hour_posts - в этом случае это уникальная строка по md5 сумме которой и будет сохранён sql запрос, при повторном запросе т.к. мы передаём в функцию не меняющийся sql запрос, а фиксированную строку, будет выдан кеш ровно того запроса который нам нужен и если время кеша не истекло, все данные будут взяты из сохранённого файла и сам sql запрос выполнен не будет.
Тут нужно отметить небольшое отличие второго метода кеширования от первого, если в первом случае запрос ничего не вернёт, т.е. не будет никаких данных, сам sql запрос не будет закеширован и при каждом выводе страницы сам sql запрос будет выполняться пока не будет каких-либо данных для вывода, во втором случае даже если данных для вывода нет, запрос будет закеширован и будет возвращать "пустоту", до тех пор, пока не истечёт время кеширования.

Ещё один пример, нужно вывести сообщения за последний час только из определённых форумов (с учётом прав доступа пользователей на форумы):

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE forum_id IN(2, 4) AND post_time>".(time()-3600);
$db->sql_query($sql);
2, 4 - в этом случае id форумов, при этом они могут меняться, т.к. у разных групп пользователей могут быть разные права доступа на форумы и запрос для кого-то может иметь такой вид:

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE forum_id IN(4) AND post_time>".(time()-3600);
$db->sql_query($sql);
первый вариант кеширования опять не подходит.. как и второй (если использовать его так-же как в примере выше):

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE forum_id IN(4) AND post_time>".(time()-3600);
$db->sql_query($sql, 600, 'forums_last_hour_posts');
в первом случае должны выводиться сообщения только из форумов 2 и 4, а во втором только из 4, но т.к. мы передаём в функцию фиксированную строку и в первом и во втором случае для пользователей с разными правами будут отображаться одни и те же сообщения (либо из первого запроса, либо из второго, в зависимости от того, пользователь с какими правами первым запросил страницу), для корректного отображения можно использовать следующий вариант:

Код: Выделить всё

$post_time=time()-3600;
$sql="SELECT * FROM ".POSTS_TABLE.'  WHERE forum_id IN(2, 4) AND post_time>%1$s';
$db->sql_query(sprintf($sql, $post_time), 600, md5($sql));
1. мы выносим вычисление даты последнего часа в отдельную переменную

Код: Выделить всё

$post_time=time()-3600;
2. заменяем в sql запросе вынесенный код на "заполнитель"

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE.'  WHERE forum_id IN(2, 4) AND post_time>%1$s';
3. в функцию в качестве строки по которой будет вычисляться md5 сумма передаём md5 сумму самого sql запроса, а т.к. мы вынесли время из запроса и оно меняться не будет, у нас остаются только id форумов, которые могут меняться и на основе их и будут создаваться разные md5 суммы sql запроса для пользователей с разными правами доступа к форумам

Код: Выделить всё

, md5($sql));
далее, для того, чтобы в функцию передавался реальный запрос, мы меняем "заполнитель" на дату "последнего часа"

Код: Выделить всё

$db->sql_query(sprintf($sql, $post_time)
всё.., строго говоря вариант из первого примера:

Код: Выделить всё

$sql="SELECT * FROM ".POSTS_TABLE."  WHERE post_time>".(time()-3600);
$db->sql_query($sql, 600, 'last_hour_posts');
можно так же переделать подобным образом:

Код: Выделить всё

$post_time=time()-3600;
$sql="SELECT * FROM ".POSTS_TABLE.'  WHERE post_time>%1$s';
$db->sql_query(sprintf($sql, $post_time), 600, md5($sql));
но это выглядит и читается немного "сложнее", поэтому можно обойтись и тем способом.
Аватара пользователя
9CaraTT
Благодарил (а): 230 раз
Поблагодарили: 228 раз
Сообщения: 3085
Зарегистрирован: 13 мар 2011, 15:23
Сообщение

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

05 ноя 2013, 03:52

так поступить можно не со всеми же запросами? что-то требует выполнению к прмеру мод ремутации, он требует постоянное обновление
Аватара пользователя
PPK
Администратор
Благодарил (а): 82 раза
Поблагодарили: 1621 раз
Сообщения: 10284
Зарегистрирован: 21 мар 2009, 17:13
Сообщение

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

05 ноя 2013, 10:23

конечно.., если есть моды/код который требует постоянного (онлайн) обновления, кешировать его не стоит.
Аватара пользователя
9CaraTT
Благодарил (а): 230 раз
Поблагодарили: 228 раз
Сообщения: 3085
Зарегистрирован: 13 мар 2011, 15:23
Сообщение

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

06 ноя 2013, 10:55

Всёровно за тему спасибо, очень позновательно

Вернуться в «F.A.Q.»