Jump to content


Photo
- - - - -

Импорт 300 000 материалов и оптимизация работы JBZoo для работы с большими объемами данных

рецепт оптимизация импорт

43 replies to this topic

#1 tapakan

tapakan
  • JBZoo User (rus)
  • User rate: 43.6
  • posts: 624
  • topics: 22

Posted 20 June 2014 - 08:19

*
POPULAR

Мы специально провели почти неделю издеваясь (в буквальном смысле) над импортом, Zoo и сервером, чтобы найти узкие места в производительности и узнать сможет ли JBZoo работать с большим объемов материалов.
 
Почему JBZoo может тормозить при больших объемах?

  • Во-первых, изначально Zoo и JBZoo  не были предусмотрены под большие нагрузки и объемы, в основном из-за самого Zoo и структурой базы данных Zoo. Разработчики Zoo (YOOtheme) сами наверное не рассчитывали, что подобные объемы будут использоваться на их платформе. Но, у нас есть пару вариантов, которые смогут помочь при работе с большими объемами.
  • Во вторых, чудес не бывает и производительность не берется из неоткуда.
  • В третьих, сотни тысяч материалов - это реально очень много. Пожалуйста, не утверждайте обратное без серьезных обоснований.
  • Будьте реалистами а не сказочниками  ;)

Некоторые из решений ниже, при определенных условиях, можно использовать на обычных сайтах. Только не нужно слепо все копировать - сломаете сайт! Думаем…
и бекапимся...
 
Условия тестирования
 
Сначала определимся, что мы подразумеваем под “большим объемом” ?

  • Если количество материалов превосходит 100 000.
  • Количество категорий для этих(!) материалов от 500 и выше. Тут большую роль играет количество взаимосвязей между категориями и материалами.

Сервер у нас отдельный, “железный” и полностью наш - FastVPS (EX-4)

  • Процессор: 8 ядер, 3,4Гц, Intel
  • Память: 16 GB
  • HDD: RAID, почти 3000 Gb
  • Тест произв-ти JBZoo (116 попугаев): http://llfl.ru/d6uoj

Софт

  • Debian 7
  • Apache 2.4 + Nginx 1.0
  • MySQL 5.5
  • PHP 5.4 + xCache 2.x
  • Joomla: 3.3.1
  • JBZoo: 2.1.4 Pro
  • Zoo: 3.1.6

Сразу же оговорюсь. Сервер наш - это далеко не обычная VPS-ка и  тестировали на нем из соображений:

Серьезный сервер = Серьезный сайт + Серьезные объемы

 
Если вы решили на виртуальном хостинге в 300-500 рублей делать что-то подобное, то я могу только слезами на глазах пожелать вам лишь... “удачи”  ;)
 
К слову, VPS за 500 рублей будет по определению медленнее, чем шаред за те же деньги.

 

 

Импорт 300к+ материалов и 500 категорий
 
Мы тестировали следующий вариант контента

  • Всего порядка 320 000 материалов
  • Примерно 510 категорий
  • Примерно у 30 000 материалов привязка к 10 категорий одновременно. Остальные материалы - только 1 категория.
  • В типе материала - 9 текстовых элементов (Text) и элемент цены (JBPriceAdvance).
  • У элементов разные значения - числовые, строковые и дата.
  • Уникальность простых повторяемых значений элементов в пределах 30 штук.
  • В каждом сотом материале элементы повторяемые, примерно 4.
  • Размер импортируемого файла примерно 74мб.
  • Категории создавались “на лету”.

Условия тестирования скорости импорта

  • 100 000 разных материалов.
  • Файл примерно 74 мегабайта.
  • Шаг импорта - 100 материалов за раз (т.е 1 000 шагов).
  • Без оптимизации - Чуть больше полутора часов.
  • Со всеми оптимизациями (ниже) - примерно 50 минут

Дополнительные тесты показали, что размер файла большой роли не играет. Выигрыш (или проигрыш) “смазывается” когда дело идет к концу. Я грузил одним большим, чтобы не отрываться от чая.
 
Несколько ускоряет манипуляция с размером шага. Тут все зависит от ваших данных. Только экспериментами можно найти истину… У нас это было 100 за раз.

 

Как выглядит база после импорта?

 

94u.png

 

* особое внимание стоит обратите на выделенные колонки 

Способы разгона импорта
 
Помним! Код, который мы будем удалять, написан там не от хорошей жизни, потому что программисты скучали. Комментирование кода сказывается на функционале вашей системы!

Убираем проверку алиаса на уникальность
(Только если вы уверены в уникальности алиасов в csv файле!)
 
Файл - /administrator/components/com_zoo/tables/item.php  метод save()
Комментируем следующие участки кода.

// Проверка уникальности
if ($this->app->alias->item->checkAliasExists($object->alias, $object->id)) {
     throw new ItemTableException('Alias already exists, please choose a unique alias');
}

Файл - media\zoo\applications\jbuniversal\framework\helpers\jbimport.php
примерно на 382 строке комментируем

$item = $this->_checkItemAlias($item);

Последствие: Фатальная ошибка при совпадении alias’ов. Придется перезапускать импорт.
 
 
Отключаем индекс Zoo
Файл - /administrator/components/com_zoo/tables/item.php метод save()

//Zoo index
foreach ($object->getElements() as $id => $element) {
// get search data
    if ($data = $element->getSearchData()) {
        $search_data[] = "(".$object->id.", ".$db->quote($id).", ".$db->quote($data).")";
    }
}

// delete old search data
$query = "DELETE FROM ".ZOO_TABLE_SEARCH
." WHERE item_id = ".(int) $object->id;
$db->query($query);

// insert new search data
if (count($search_data)) {
$query = "INSERT INTO ".ZOO_TABLE_SEARCH
." VALUES ".implode(", ", $search_data);
$db->query($query);
}

Последствие: Теряется возможность поиска фильтра по textarea и стандартного поиска Joomla.

 

Отказываемся от индекса JBZoo во время импорта
Файл - /media/zoo/applications/jbuniversal/framework/events/jbevent.item.php метод saved()
Комментируем весь код

// vars
$app      = self::app();
$item     = $event->getSubject();
$itemType = $item->getType()->id;

        // hack for JBZoo import optimization
if ($item->getParams()->get('jbzoo.no_index', 0) == 1) {
    return null;
}

// update index data
$app->jbtables->checkSku(true);

$indexTableName = $app->jbtables->getIndexTable($itemType);
if ($app->jbtables->isTableExists($indexTableName, true)) {
    JBModelSearchindex::model()->updateByItem($item);
}

Последствие: Сохранение и редактирование материалов не будет наполнять индекс. Придется после импорта (и любых изменений материалов) запускать переиндексацию вручную.
 
 

 
Играемся с шагом импорта
Файл media\zoo\applications\jbuniversal\framework\helpers\jbimport.php константа 

STEP_SIZE = 50

Попробуйте ее увеличить до 100-200. Очень большие значения сделают только хуже. Все зависит от "однородности" ваших данных параметров вашего сервера.
 

 
Оптимизация JBZoo Некоторые советы

  • Нет никакого смысла импортировать большие объемы под windows. Проблемы NTFS и мелких файлов PHP “съедят” ваш сайт при любом процессоре и даже на SSD дисках.
  • Как показали результаты тестов, при большом количестве импортируемой информации,  переиндексация пройдет быстрее отдельным процессом после создания материалов.
  • От модуля JBZoo Search List по возможности лучше отказаться т.к он использует наиболее тяжелые запросы в базу для такого количества.
  • Отключаем все лишние плагины Joomla. Особенно плагины finder и search. Они генерируют дополнительную нагрузку на базу и сайт в целом.
  • В фильтре меньше использовать элементы с уникальными значениями - radio, select и т.д.
  • Используйте точный поиск. Полнотекстовый очень требовательный по определению.
  • НЕ используйте множественные сортировки. Сортировка - это всегда тяжелая операция.
  • НЕ используйте сортировку от Zoo (она кривая, особенно алфавитная)
  • НЕ используйте альфаиндекс (поиск по букве и выборка уникальный букв для блока - очень тяжелые операции)

 

Ускорение сайта

  • Обязательно включаем кеширование (для JBZoo большой разницы нет между стастический и динамический)
  • Желательно НЕ использовать файловый кеш. Хорошо справляется модуль php memcache.
  • Если у вас статический контент, то можно включить плагин кеширования. Он полностью сохраняет html страницы. Осторожно плагин никак не проверяет, обновились ли данные.
  • Если вам не важны данные о начале и окончании публикации материала, можно изменить sql запрос. На 100 000 материалов это помогло выиграть ~5 секунд из 17

 

Изменить запрос необходимо для категории в самом Zoo и в JBZoo
 
1. Файл - administrator\components\com_zoo\tables\item.php . Метод getByCategory.
Удаляем из него следующие строки

." AND a.".$this->app->user->getDBAccessString($user)
." AND (a.publish_up = ".$null." OR a.publish_up <= ".$now.")"
." AND (a.publish_down = ".$null." OR a.publish_down >= ".$now.")": "")

2. Файл - media\zoo\applications\jbuniversal\framework\models\jbmodel.php . Метод _getItemSelect
Избавляемся от кода

->where('tItem.' . $this->app->user->getDBAccessString())
->where('(tItem.publish_up = ' . $this->_dbNull . ' OR tItem.publish_up <= ' . $this->_dbNow . ')')
->where('(tItem.publish_down = ' . $this->_dbNull . ' OR tItem.publish_down >= ' . $this->_dbNow . ')')

 

 
Еще полезная информация о базе и фильтре от SmetDenis ...
Источник http://forum.jbzoo.c...udet-bystree-e/

  • Скорость работы фильтра не зависит от настройки тизеров. Как понимаю, скорость фильтра - это непосредственно скорость поиска, т.е сопутствующих запросов в БД. Не путайте с выводом результата и генерацией HTML
  • Если у вас одновременно на странице выводится несколько десятков (а то и сотен) тизеров, тогда конечно, вывести данные напрямую из объекта материала будет быстрее, минуя проверку полей на доступ и рендеры шаблонов самих элементов. Тут можно выиграть только если используются заведомо сложные элементы (цена, каскадные селекты например), где нужно не просто вывести значение, а еще вычислить что-нибудь или показать виджет.
  • Если говорить о поиске, то опять же зависит от того, по каким полям вы ищите, какой поиск и какого рода данные там хранятся. Лучше смотреть на конкретные примеры. Однозначно нельзя сказать. Запросы в базу собираются динамически + умеют частично и эффективно кешироваться на уровне MySQL.

Вот несколько мыслей по поводу фильтров

  • Фильтр оперативнее ищет по числам, т.е оптимизация на уровне MySQL. На втором месте будут даты и самый медленный - это текст.
  • Точный поиск всегда работает в разы быстрее полнотекстового (учите SQL).
  • Поиск по textarea - самый медленный (причин много, основы программирования).
  • Если вы ищите по категориям и у вас используется множественная привязка одного материал ко многих (и таких привязок оооочень много), то это снижает скорость. Например, у нас 100 категорий и 2000 материалов. Максимально привязано все ко всему. Получается, что 2000 * 100 ~ 200 000 будет участвовать в запросе. Но я лично не представляю логическое обоснование таким сайтам =)
  • 300 категорий - это много только для человека. MySQL легко орудует десятками тысячами записей. Для него это рутина и бытовуха =).
  • Множественные поля конечно усложняют поиск, но не критично. Конечно если у вас на одно поле не приходится 10+ значений и подобных полей в материале 5-10. Т.е получается что на 1 материал индекс будет хранить как минимум 10 и более записей.
  • Большое количество полей в одном типе материала проявит себя только после ~20-30 штук (считаю только те, которые содержат полезные(!) данные для поиска). Просто в этом случае можно упереться в некоторые ограничения MySQL. Не критично и зависит от пунктов выше.
  • Количество приложений и типов сильной роли не играет, т.к на уровне базы данных типы имеют физически разные таблицы, а каталоги - это простейшее индексируемое поле.
  • … ищите хороший хостинг (в JBZoo есть система тестирования скорости)

---
 
В силу невероятно тупых (нет других слов) мнений о базах данных, их размерах и кол-ве запросов в популярных очерках незадачливых, не побоюсь этого слова, "web-мастеров" - у людей складываются не правильные понятия о принципе работы сайта в целом.
 
Сразу вспоминаю мой Joomla-Book.ru, главная страницы. ArtioSEF добавляет 250 запросов. И че?)) Летает =)
 
Скажу вам как человек, который делал даже такие вещи как автодополнение на лету по 8 миллионной базе весом в 35Гб. Все зависит от конкретного запроса и индексов в базе. Можно сделать 300 запросов, при этом сайт будет грузится 0,5 сек или 10 запросов в туже самую базу за теми же данными, но уже все будет грузится в 10 раз дольше.
 
Поэтому лучше рассматривать конкретные примеры, конкретный хостинг, конкретные данные.

 
 

В заключение от автора
Работу Zoo и JBZoo проверили на 320 тысячах материалах и 500 категориях.
До оптимизации загрузка страницы категории длилась ~17 секунд - 20 материалов на странице, у каждого по 10 элементов + заведомо тяжелые модули.
 
После всех выше описанных оптимизаций скорость загрузки категории увеличилась до ~3 секунд, из которых 2 занял рендеринг шаблона (Список материалов), ~0.5 секунд на вывод JBZoo Module search(Очень много опций), ~0,5 секунды для модуля JBZoo Module Search List.
 
Это только базовая оптимизация (а ускорение уже в 6 раз), дальше нужно смотреть каждый сайт индивидуально.
 
Оперативной памяти понадобилось 90мб (очень много HTML и Zoo начинает течь по памяти, причину не искали).
 
Сами видите, какие потребовались ресурсы и силы, что бы при больших объемах работоспособность сайта сохранилась.
Согласитесь, не каждый дешевый хостинг может себе это позволить.
 
Если вы решили делать сайт на JBZoo под большие объемы информации приготовьтесь раскошелиться на хороший сервер, хотя, это обязательное условие для нормальной работы сайта.
 
Считаю, что JBZoo вполне справилось с объемом 100к+ и уж тем более справится с типичными 3000 из магазина.
Главное - не отключайте голову ;)

PS С нетерпением жду ваших комментов, замечаний и наблюдений. Открыт для срача холивара.

 

Attached File  patch.zip   20.18KB   382 downloads

  • administrator\components\com_zoo\tables\item.php - убрана индексация зуу, проверка alias на уникальность, проверка по диапазону дат, доступу пользователя.
  • components\com_zoo\controllers\default.php - отключаем подсчет количества материалов для категорий. Бережем оперативную память.
  • media\zoo\applications\jbuniversal\framework\events\jbevent.item.php - выключаем индексацию зуу.
  • media\zoo\applications\jbuniversal\framework\helpers\jbimport.php - убираем проверка alias на уникальность.
  • media\zoo\applications\jbuniversal\framework\models\jbmodel.php - Изменяем sql запрос. Нет проверка по диапазону дат, доступу пользователя.

Edited by tapakan, 07 July 2014 - 10:01.

  • 12

#2 isay777

isay777
  • JBZoo User (rus)
  • User rate: 113.4
  • posts: 1878
  • topics: 232

Posted 24 June 2014 - 19:02

будем пробовать. 


  • 0
ХОСТИНГ для сайтов jbzoo (все попугаи)

#3 Den

Den
  • JBZoo User (rus)
  • User rate: 0
  • posts: 178
  • topics: 47

Posted 03 July 2014 - 21:04

Какой шаблон и что вообще посоветуете для информационного портала на который планирую загрузить 1 500 000  item.

 

Стоит ли вообще делать такой портал на jbzoo?

 

Если да то какой лучше VPS выбрать в части параметров?

 

 

Спасибо)).


  • 0

#4 SmetDenis

SmetDenis
  • Administrators
  • User rate: 139.4
  • posts: 16232
  • topics: 200

Posted 04 July 2014 - 06:52

Каким образом шаблон связан с количеством материалов?
1 500 000 - будет тормозить без специальных оптимизаций. Чуда не будет. Если нет понимания как работает SQL, то не стоит.
Берите dedicated server
  • 0
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как можно скорее!



— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.


#5 Den

Den
  • JBZoo User (rus)
  • User rate: 0
  • posts: 178
  • topics: 47

Posted 04 July 2014 - 15:59

Никаким я просто уточнил)

 

 

Оптимизаций описанных выше хватит? или что то еще рекомендуете делать?

Спасибо.


  • 0

#6 Den

Den
  • JBZoo User (rus)
  • User rate: 0
  • posts: 178
  • topics: 47

Posted 04 July 2014 - 16:27

Нужен совет, мне лучше оптимизировать jbzoo или dle использовать?

Спасибо.


  • 0

#7 SmetDenis

SmetDenis
  • Administrators
  • User rate: 139.4
  • posts: 16232
  • topics: 200

Posted 04 July 2014 - 16:35

Даже не знаю что вам дополнительно ответить на эти вопросы.
Все зависит от вашей базы, фильтров, запросов и т.д. Как зависит - написано выше.
  • 0
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как можно скорее!



— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.


#8 Den

Den
  • JBZoo User (rus)
  • User rate: 0
  • posts: 178
  • topics: 47

Posted 06 July 2014 - 10:09

/media/zoo/applications/jbuniversal/events/jbevent.item.php

 

Находится по пути 

 

/media/zoo/applications/jbuniversal/framework/events/jbevent.item.php

 

 

и удаляю строки 

  1. ." AND a.".$this->app->user->getDBAccessString($user)
  2. ." AND (a.publish_up = ".$null." OR a.publish_up <= ".$now.")"
  3. ." AND (a.publish_down = ".$null." OR a.publish_down >= ".$now.")": "")

и сайт не работает.

 

 

Могли бы вы прикрепить к теме измененные файлы.

Спасибо.


  • 0

#9 tapakan

tapakan
  • Topic Starter
  • JBZoo User (rus)
  • User rate: 43.6
  • posts: 624
  • topics: 22

Posted 07 July 2014 - 10:21

Добавил патч, что бы установить, распакуйте архив в корень сайта.


  • 1

#10 Den

Den
  • JBZoo User (rus)
  • User rate: 0
  • posts: 178
  • topics: 47

Posted 09 July 2014 - 18:19

С настройками разобрался).

Теперь проблема с заливом на сервер. Посоветуйте нормальный сервер по приемлемой цене. Т.к. на текущем 55 попугаев у сайта и 100 к., грузится 980 минут)).

 

Спасибо.


  • 0





Also tagged with one or more of these keywords: рецепт, оптимизация, импорт

Click to return to top of page in style!