Снизить нагрузку на БД при выводе случайных материалов

Главные вкладки

Аватар пользователя astrameridian astrameridian 15 ноября 2013 в 0:31

Нужно выводить блок из 3-х случайных книг на сайте, состоящий из Заголовка, Уменьшенной картинки (берётся 1-ая картинка из поля body с помощью модуля teaser_image) и небольшого текста (первые 200 знаков поля body).

При этом на сайте 1000 книг, каждая нода - глава книги объёмом в среднем 50 000 знаков. Насколько я понимаю, чтобы вывести через views такой блок, нужно будет сделать очень ресурсоёмкий запрос ко всем нодам типа "книга", в частности обработать каждое поле body и вырезать из него первые 200 знаков, и потом показать случайно 3 элемента... И делать так каждый раз при показе страницы или её обновлении. Так как выборка большая, а вывод случайный, кеширование блока работать корректно не будет, либо будет создавать не малую нагрузку при каждом сбросе кеша.

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

2. Может есть другой способ, чтобы выводить такой блок случайных материалов, но при этом значительно снизить нагрузку на базу данных?

Помогите, а то сайт перегружается, а без случайных материалов, он слишком статичный и не интересный.

Комментарии

Аватар пользователя alex_shut alex_shut 15 ноября 2013 в 0:41

да... алгоритмик ТС написал шикарный.
Интересно глянуть сколько при таком раскладе проживет сайт )) Хоть тысяча юзеров успеет зайти на ноду? )

Аватар пользователя astrameridian astrameridian 15 ноября 2013 в 2:25

Может проблема с нагрузкой в том, что таких блоков на сайте много (5 штук), все выводят информацию случайно, кстати по другим блокам и выборка намного более сложная с множеством типов материалов.

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

Думаю в результате этого выпали вчера все страницы из индекса (20 000). При этом во время добавления страниц в ручную (основных разделов сайта), в какой-то момент страницы опять восстановились, но видимо из-за того, что коннект не стабильный, опять выпали...

Поэтому ищу пути ускорения (пока временно в каких-то блоках отключил вывод картинок, а где-то отказался от вывода обрезанного текста тела ноды, только заголовки)...

Аватар пользователя Chyvakoff Chyvakoff 15 ноября 2013 в 9:05

"astrameridian" wrote:
Можно ли сделать какое-то поле, например body_mini

У ноды есть $node->teaser
"astrameridian" wrote:
поле body и вырезать из него первые 200 знаков

Где тут нагрузка то...
"astrameridian" wrote:
Помогите, а то сайт перегружается, а без случайных материалов, он слишком статичный и не интересный.

От рандомных выборок сайт мокрый и шевелится становится интересным?
Кэшируй это дело.

Или можно так.
Если нужен рандом из большой таблицы, то сортировка по rand() будет нагрузочной, так сказать. Тогда делаешь один запрос на выбор всех id из этой таблицы. Потом перемешиваешь этот массив айдишников. Берешь первые три штуки(или сколько там надо). И потом в основном запросе указываешь where id in(твои айдишники).

Аватар пользователя bsyomov bsyomov 15 ноября 2013 в 16:00

Запрос случайных данных будет работать не так - сначала будут выбраны случайные материалы в нужном количестве, потом будет произведена обрезка, при форматировании, и mysql это уже не затронет совсем.

1000 записей из которых надо выбрать случайные это очень мало - это не нагрузка. Можно было бы париться, если бы записей были миллионы, и ещё были бы сложные join. Тогда да, надо было бы оптимизировать, выбирая сначала случайные id, потом данные по ним.

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

Аватар пользователя astrameridian astrameridian 16 ноября 2013 в 8:07

Спасибо "bsyomov" за подробное объяснение логики работы базы в данном случае.

1. Хотел бы уточнить, действительно ли объём ноды не имеет значения? (например если там текста на 100 000, 300 000 знаков будет, чтобы обрезать нужно ведь первые 200-600 знаков).

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

3. Посещаемость сайта не высокая 300-500 посетителей в сутки, поэтому сброс кэша каждые 5 минут на всём сайте в 30 000 страниц (блоки размещены на всех страницах сайта), не даст эффекта в производительности? Сейчас мин. время кеша стоит 1 час, максимальное 3 часа в настройках производительности сайта.

4. Влияет ли частота запуска крона на производительность сайта? Было 3 часа, сейчас каждый 1 час. Может ли быть такое, что если редко запускать, то накапливается больше заданий, которые потом трудно обработать, и лучше запускать почаще?

На данный момент отключение вывода картинок и др. изменения в блоках помогли избавиться от проблемы, главная страница стала загружаться за 1.5-3 секунды, 350 кб со всем контентом, css и скриптами в оптимизированном состоянии, а раньше минимальное значение было 3 секунды. В итоге проверяя нагруженное представление вывода списка тизеров 10 статей с крупными картинками, обработанными модулем teaser_image и со статистической информацией (Опубликовано: пт, 15.11.2013 - 17:49 . Всего просмотров: 46, из них сегодня: 2, последний просмотр: 56 минут 45 секунд назад), а также выводился блок оценки (vote), если раньше при запросе ответа Яндекса на страницу: http://webmaster.yandex.ru/server-response.xml первый запрос был больше 5 секунд и выдавалось сообщение об ошибке связи с сервером, то сейчас максимум 2.5 секунды при первичном запросе и 400 мс при повторном и никаких ошибок нет.

Также раньше html карта сайта, сделанная во views, выводила по 500 материалов на одной странице, с пейджером всех страниц, где выводился заголовок и 200 знаков из тела ноды. И было замечено, что некоторые страницы вообще не загружались, видимо не хватало оперативной памяти, даже увеличив значение до 456 мб (думаю из-за того, что на той странице грузились ноды книг с большим кол-вом текста в нодах)... Сейчас вывел через views только заголовки по 2200 ссылок на странице и просто сохранил результат в виде нтмл страницы и загрузил в ручную на хостинг (получилось 3 файла по 900 кб каждый), отключив представление. Возможно это также помогло снизить нагрузку.

5. Может кто подскажет автоматизированное средство создания html карты сайта, без большой нагрузки на сайт?

Ещё раньше выводились 2 блока голосования (опроса), визуально они тормозили загрузку страниц сайта, и также выводился блок Популярное содержимое по 10 ссылок: За всё время, За сегодня, За последнее время. Были отключены последние 2, так как скорее всего они динамически запрашивали информацию из базы данных.

Аватар пользователя voviko voviko 16 ноября 2013 в 12:09

1. не имеет,
2. вывод картинок,никак не влияет на производительность
3. постсавьте сутки.
4. крон может повесить что угодно, и задач у него немного, на стандартном сайте, и если вы на крон не вешали что либо своё, то можно запускать раз в месяц, или вручную.
5 xmlsitemap для поисковиков хорошо, а 500 страниц собирать через views, не надо, этим можно сайт повесить.

Аватар пользователя alex_shut alex_shut 16 ноября 2013 в 12:19

"astrameridian" wrote:
2. Возможно нагрузка была больше из-за обработки картинок (ведь для вывода в блоке, модуль её должен найти в теле ноды и уменьшить, а это явно должно создавать нагрузку).

да тут еще и отсутствие понимания работы друпала с файлОм.
Когда в поле "имедж" загоняется картинка, она сразу копируется и ресайзится в соответствии с указанными прессетами. А потом тупо берется нужное из известного места.
Никаких мега поисков и ресайзов по запросу к БД не происходит.

"astrameridian" wrote:
На данный момент отключение вывода картинок и др. изменения в блоках помогли избавиться от проблемы, главная страница стала загружаться за 1.5-3 секунды, 350 кб со всем контентом, css и скриптами в оптимизированном состоянии, а раньше минимальное значение было 3 секунды.

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

Аватар пользователя astrameridian astrameridian 16 ноября 2013 в 12:33

"voviko" wrote:
5 xmlsitemap для поисковиков хорошо, а 500 страниц собирать через views, не надо, этим можно сайт повесить.

xmlsitemap не делает html карту сайта, а при создании карты для поисковиком, он не умеет включать страницы, созданные модулем smart_paging (он разбивает ноду на страницы атоматом по заданному числу символов или слов). Поэтому пока делаю карту в ручную с помощью бесплатного софта: http://www.auditmypc.com/free-sitemap-generator.asp который сканирует весь сайт и позволяет создавать карту для поисковиков (включая все найденные страницы). Аналога ему среди модулей для Drupal 7 пока не нашёл.

html карта позволяет страницам иметь более высокий уровень вложенности, если html карта включает все страницы, то уровень вложенности вроде будет 2 (если главная это 0, а карта это 1), а пока с помощью views можно получить только список нод, поэтому если разбивается нода на страницы с указанием внизу пейджера со списком всех страниц, то уровень страницы получается равен 3.

5.1. Если кто-то знает решение автоматом создавать карту сайта для поисковиков с указанием всех страниц (включая созданные модулем smart_paging), подскажите как это реализовать?
5.2. Если кто знает как сделать html карту сайта автоматом, но без нагрузки на сайт (без views видимо), также поделитесь опытом.
5.2.1. Ну а если можно будет сделать html карту сайта автоматом, да ещё и включать туда все страницы, включая созданные модулем smart_paging, и с разбивкой по 2 200 ссылок на 1 странице (где то читал, что Яндекс не воспринимает страницы, если там более 2 с лишним тысяч ссылок, не помню точно сколько, то ли 2500, то ли 2700...) с указанием списка всех страниц, то будет совсем здорово!