Уменьшение запросов в БД (микрохак))

2010
Привет всем !

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



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

Я настроил у себя кеширование примерно от 3 до 30 минут на разные модули ,
попутно отслеживая ко-л во запросов и время генерации.
На главной удалось снизить запросы с ~100 до ~55.

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

Но можно немного и схитрить )

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

Логика хака такова :
Для Незарегистрированного пользователя не будет запросов в базу о жизни кеша.
Соответственно и модули не будут лишний раз дергать базу ..
Кеш в обычном режиме будет обновляться только при посещении сайта зарегистрированным пользователем.
И соответственно это обновление увидят и гости на сайте, т.е. сайт по прежнему остается динамичным !

Это ,например мне, позволило дополнительно снизить запросы на главной с 55 до 36 для гостей..
т.е. на каждую сотню гостей , только на на главной страничке, убрано более 1900 запросов к БД !)
Время жизни кеша на это никак не влияет , можно хоть 1 минуту ставить ..

Делается все в файле core/classes/page.class.php
Нужно найти функцию : public function printModules($position)
и в ней вот эти строки :

Код PHP:
if( $mod['is_external'] ){
if (file_exists($modulefile)){
require_once $modulefile;
if ($mod['cache'] && $inCore->isCached('module', $mod['mid'], $mod['cachetime'], $mod['cacheint'])){
$modulebody = $inCore->getCache('module', $mod['mid']);
$callback = true;
} else {
$config = $inCore->yamlToArray($mod['config']);
$inCore->cacheModuleConfig($mod['module_id'], $config);
ob_start();
$callback = $mod['content']($mod['module_id']);
$modulebody = ob_get_clean();
if($mod['cache']) { $inCore->saveCache('module', $mod['mid'], $modulebody); }
}
}
}
и заменить на :

Код PHP:
if($mod['is_external']){
if (file_exists($modulefile)){
require_once $modulefile;
if (!$inUser->id){
if ($mod['cache']){$modulebody = $inCore->getCache('module', $mod['mid']);$callback = true;}
else {$config = $inCore->yamlToArray($mod['config']);$inCore->cacheModuleConfig($mod['module_id'], $config);
ob_start();$callback = $mod['content']($mod['module_id']);$modulebody = ob_get_clean();}} 
else {
if ($mod['cache'] && $inCore->isCached('module', $mod['mid'], $mod['cachetime'], $mod['cacheint'])){$modulebody = $inCore->getCache('module', $mod['mid']);
$callback = true;}
else {$config = $inCore->yamlToArray($mod['config']);$inCore->cacheModuleConfig($mod['module_id'], $config);
ob_start();$callback = $mod['content']($mod['module_id']);$modulebody = ob_get_clean();
if($mod['cache']) {$inCore->saveCache('module', $mod['mid'], $modulebody);
}}}}}

Ну и как обычно ... Не забудьте сделать резервную копию и тд и тп ..
glasses
маленькое ускорение instantvideo ) *микрохак | Исчезающие плохие комментарии (*Хак))
Комментарии (28)
picaboo 6 мая 2012 в 13:35 +2
Спасибо за идею :)

кстати у вас на морде <!-- 1.5993(37) -->
а если войти в блоги <!-- 0.0747(63) -->

что-то всеравно тормозит, запросов в два раза меньше, а время генерации в 20 раз больше
KS 6 мая 2012 в 14:16 0
На главной модули из iMaps выводятся ...
А их к сожалению кешировать нельзя .. Поэтому и время генерации такое ..
Если их отключить то будет как в блогах .

Но честно говоря 1.5 что то совсем много . У меня больше 0.4 не было на главной ..
Если есть возможность , попробуйте пару раз обновить страничку , посмотрите сколько покажет .
picaboo 6 мая 2012 в 21:40 +1
обновлял, лучший результат <!-- 0.3683(35) --> но обычно в районе секунды и выше
KS 7 мая 2012 в 02:59 +1
Нашел причину ...
Это как я и думал модули мапса. Больше всего грузит новостной , запрос в нем тяжелый идет на вывод всего. буду его ковырять на днях )
Хотя если в мапсе включить режим одного города, то он летать начинает..
Получается все связано с детектом города и отсевом вывода после этого.
Спасибо Вам и Sjen за бдительность !

Попробовал с отключением всего Мапса , главная стала - <!-- 0.0470(32) -->
letsgo 6 мая 2012 в 13:49 +1
Плюс за хак.
fact 6 мая 2012 в 13:52 0
а что реально помогает?
KS 6 мая 2012 в 14:24 0
Помогает !
У меня запросов без кеша около 100 на главной должно бы быть ..
С кешем 55 минимум (пока он живет)
С хаком (вне зависимости жизни кеша) 36-37
universe 6 мая 2012 в 18:17 +1
на счет хака, если страницу никто из зарегистрированных пользователей не посещал в течении 2 недель. То гости будут видеть кешь 2-х недельной давности?
KS 6 мая 2012 в 18:25 0
Да.
В этом и логика. Контент в основном обновляют зарегистрированные пользователи.
universe 7 мая 2012 в 12:02 +2
а если сделать, что то в виде кнопки обновить кешь. И весь вешь на сайте автоматом обновляется
KS 7 мая 2012 в 17:33 0
Можно сделать , но какой смысл? Это нужно только если у вас контент могут добавлять незарегистрированные пользователи ..
А если какой либо модуль например парсит инфо, то его можно просто не кешировать и он будет обновлятся и у гостей )
googlebot 7 мая 2012 в 23:45 +1
есть уже такая кнопка - поищите в блогах
universe 8 мая 2012 в 21:06 +1
знаю эту кнопку но дело в том, если очиститься кешь то модули которые не открывали зареганные, то у гостей пусто будет или все таки пойдет запрос на создание кеша?
Дмитрий 9 мая 2012 в 03:26 +1
Супер элементарно и эффективно, но...
Не работает вот с этим модулем: http://instantcms.ru/blogs/moi-blozhek/modul-socialnye-zakladki.html
Гости не видят иконок социалок, только сам блок.
У зареганных всё хорошо.
Дмитрий 9 мая 2012 в 03:39 +1
Хотя, похоже, что это особенности ИЕ.
ИЕ8 залогиненный юзер тоже не видит эти закладки и лог из браузера:

Сведения об ошибке на веб-странице

Агент пользователя: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.3; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C)
штамп времени: Wed, 9 May 2012 00:32:52 UTC


Сообщение: '0' - есть null или не является объектом
Строка: 18
Символ: 1
Код: 0
URI-код: .../modules/mod_soccontent/bookmarks.js

В строке 18 находится такой код:
btn+='<a href="http://'+services[0]+'" target=_blank><img src="'+dir+services[1]+'" alt="Добавить в '+services[2]+'" title="Добавить в '+services[2]+'" style="border:0;padding:0;margin:0 4px 0 0;"></a>';}

Ох уж этот ИЕ - ВСЕГДА проблемы ))
KS 9 мая 2012 в 04:11 0
Этот хак вообще ни как не влияет на работоспособность модуля .
Попробуйте отключить кеширование блока соц закладок.
Заметил такую вещь , что если включать кеш для модулей у которых js прописан прямо внутри кода ,
вылазиют всякие глюки ..
У меня так же с было с модулем вывода новостей на js , решил сунуть код внутрь , а его "понесло"
по экрану )..
SJen 9 мая 2012 в 10:49 0
а каким образом был "прописан прямо внутри кода"?
в tpl шаблоне через "add_js file"?
Дмитрий 9 мая 2012 в 23:56 +1
Может кто подскажет, что это же за трабла с ИЕ8? :)
http://made-in-handmade.com - вот здесь модуль BOOKMARK
KS 10 мая 2012 в 05:25 0
Нет , модуль без tpl, вся работа внутри module.php ,
Скрипт мизерный , я его легко вставил внутрь и он заработал , но
как то криво .. причем функционал в норме а дизайн перекосило в ИЕ.

Это наверно как в случае с вашим кешированием и ИЕ ,
скорее всего что то похожее ..
Дмитрий 9 мая 2012 в 23:51 +1
По умолчанию кеш был выключен. Включал/выключал ничего не изменилось. Но да ладно, фиг с ним с этим ИЕ8, наверное это менее 10% пользователей, не страшно. Просто в качестве информации, вдруг решение найдётся )
s21 9 мая 2012 в 12:35 0
обновлял, лучший результат <!-- 0.3683(35) --> но обычно в районе секунды и выше

а где показывается тот результат? тоже хочу проверить свой сайт...
KS 9 мая 2012 в 12:53 +1
Самый простой вариант это включить "режим отладки" в настройках сайта, и после обновления странички внизу будет видно время генерации и запросы к базе ..
Только после тестов отключить не забудьте )
s21 9 мая 2012 в 12:58 0
Спасибо!
Alon 15 апреля 2014 в 00:48 0
Это действует на движок 1,10,1 ?
KS 15 апреля 2014 в 03:19 0
да , если функция полностью такая.
У меня на 1.10 стоит, полет нормальный
Alon 19 апреля 2014 в 08:11 0
Как с вами можно связаться? мне нужно срочно решить эту проблему
Александр I 19 апреля 2014 в 10:03 0
Код для версии ICMS 1.10.1
В файле ../core/classes/page.class.php
В функции public function printModules($position)
найти (стр. 432-456):
Код PHP:
  1. // Отдельный модуль
  2. if( $mod['is_external'] ){
  3. if (file_exists($modulefile)){
  4.  
  5. require_once $modulefile;
  6. // Если есть кеш, берем тело модуля из него
  7. if ($mod['cache'] && cmsCore::isCached('module', $mod['id'], $mod['cachetime'], $mod['cacheint'])){
  8.  
  9. $mod['body'] = cmsCore::getCache('module', $mod['id']);
  10. $callback = true;
  11.  
  12. } else {
  13.  
  14. $config = cmsCore::yamlToArray($mod['config']);
  15. $inCore->cacheModuleConfig($mod['id'], $config);
  16.  
  17. $callback = $mod['content']($mod['id']);
  18. $mod['body'] = ob_get_clean();
  19. if($mod['cache']) { cmsCore::saveCache('module', $mod['id'], $mod['body']); }
  20.  
  21. }
  22.  
  23. }
  24. }
и заменить на:
Код PHP:
  1. // Отдельный модуль
  2. if($mod['is_external']){
  3. if (file_exists($modulefile)){
  4.  
  5. require_once $modulefile;
  6. if (!$inUser->id){
  7. if ($mod['cache']){
  8. $mod['body'] = cmsCore::getCache('module', $mod['id']);
  9. $callback = true;
  10. } else {
  11. $config = cmsCore::yamlToArray($mod['config']);
  12. cmsCore::cacheModuleConfig($mod['id'], $config);
  13.  
  14. $callback = $mod['content']($mod['id']);
  15. $mod['body'] = ob_get_clean();}
  16. } else {
  17. if ($mod['cache'] && cmsCore::isCached('module', $mod['id'], $mod['cachetime'], $mod['cacheint'])){
  18. $mod['body'] = cmsCore::getCache('module', $mod['id']);
  19. $callback = true;
  20. } else {
  21. $config = cmsCore::yamlToArray($mod['config']);
  22. cmsCore::cacheModuleConfig($mod['id'], $config);
  23.  
  24. $callback = $mod['content']($mod['id']);
  25. $mod['body'] = ob_get_clean();
  26.  
  27. if($mod['cache']) {
  28. cmsCore::saveCache('module', $mod['id'], $mod['body']);
  29. }
  30. }
  31. }
  32. }
  33. }
Александр 12 ноября 2014 в 21:41 0
а это работает со всеми 1.10.* ? 3-4 например