Вход • Регистрация

Очень долгий ответ при поиске по каталогу.

  • 24 октября 2014 г.
  • На сайте http://delta.spectr-site.ru/katalog-nedvizhimosti/, делаем поиск по каталогу с большим набором параметров.
    Проблема в том что при таком поиске ответ сервера составляет от 1 до 15 секунд, это связано видимо с большим кол-во объединяемых таблиц.
    Кто нибудь сталкивался с похожей ситуацией и если да то как решалась проблема?

    Один из вариантов увеличить мощность сервера, но я с таким первый раз столкнулся и хотелось бы узнать поможет ли это или же надо оптимизировать запросы к бд.
    • 24 октября 2014 г.
    • Какой красивый поиск!
      Это вы его через JS так накрутили?
    • 24 октября 2014 г.
    • Слыхал еще про танцы с бубном с mysql типа индексации и дефрагментации или что-то типа того.
      Стандартный виртуальный хостинг навряд-ли даст такие вещи делать, как и memcached настроить.
      • 24 октября 2014 г.
      • Клиент скорее всего одобрит аренду не очень жирного сервера за 3-4т.р в месяц, но боюсь и этого может не хватить так как добавится ещё поиск по карте. Есть идея заменить часть характеристик на записи в таблице shop и сортировать напрямую по ней, тогда SQL должен получится легче, но занятие это уж больно долгое.

        PS. Спасибо за оценку) Да, все элементы работают на JS.
        • 24 октября 2014 г. , редакция: 24 октября 2014 г.
        • Да, тоже сталкивался с этой проблемой и как раз тоже сайт был по недвижимости. Поиск по характеристикам спроектирован изначально не самым лучшим образом, поэтому сейчас когда в проектах необходимо организовать сложный фильтр, приходиться отказываться от Диафан в пользу других CMS.
          • 24 октября 2014 г. , редакция: 24 октября 2014 г.
          • Как решили эту проблему?
            Пробовали делать перенос характеристик в таблицу shop или выносить проект на дорогие сервера?
            • 24 октября 2014 г.
            • Пока не решали никак, судя по статистике использования данной формы, большим количеством характеристик при составлении запроса никто почти из посетителей сайта не пользуется, так что пока решили оставить как есть. Если ситуация измениться, то будем что то думать.
        • 24 октября 2014 г.
        • Возможно хостинг с SSD и большей долей/проца оперативки решит вопрос.
          вон например http://timeweb.com/ru/services/vds/ 600 рублей на 5 гигов SSD и 512 оперативки. Можно и конфигурацию mysql потюнить и memcached настроить.

          А за 3-4 тыс так можно вообще развернуться как угодно.

          Это у вас какой-то JS фремворк для форм специальный?

          • 24 октября 2014 г.
          • Огромное спасибо за совет!
            Попробую на нём развернутся. Но с поиском хочется и другое решение найти.
            Не каждый клиент хочет платить такие суммы за железо, а использовать на другие CMS из-за одного только поиска не хочется.

            Нет. Сам написал на JQuery, там же ничего сложного=)
            1. Для селектов(3 типа) 50-70 строчек примерно на каждый их вид.
            2. С чекбоксами/кнопками строчек 20.
            3. Функция, которая из html структуры делает ползунок.
            4. 6 табов для 6 видов поиска
            Всего не более 400-500 строк + JQuery UI для ползунков.

            Вот собственно и всё.
            • 24 октября 2014 г.
            • Бывают иногда проблемы для сложных запросов. Смотрите лог, или у тп хостинга спрашиваете пару самых долгих запросов (а их там действительно пара), и ставите индексы на эти таблицы. С 10 секунд падает до 0,03 какие-нибудь
              • 24 октября 2014 г.
              • Виталий, а в phpmyadmin такая кнопочка есть?
              • 24 октября 2014 г. , редакция: 24 октября 2014 г.
              • Спасибо за совет. Попробую. А запрос сложный всего 1, тот что генерирует выборку, как раз таки по причинам большого кол-ва объединений таблиц как это подробно описал Dmitry (weissfl).

                И возникает вопрос сильно ли помогут при такой проблеме индексы и я правильно понимаю что индексировать следует SHOP_PARAM_ELEMENT и SHOP?
  • 24 октября 2014 г.
  • Цитата
    Есть идея заменить часть характеристик на записи в таблице shop и сортировать напрямую по ней, тогда SQL должен получится легче, но занятие это уж больно долгое.
    - по итогу это получается самое правильное решения, для снижения ресурсоемкости фильтрации. Ну либо надо больше мощных серверов.

    Дело в том, что для хранения характеристик товара используется так называемая EAV-модель (Entity–attribute–value - сущность-атрибут-значение).

    Обычная реляционная модель данных подразумевает, что для каждой сущности заводится отдельная таблица, и для каждого атрибута в этой таблице создается столбец (в случае с магазином нам надо было бы в таблице "товар" (это сущность) создавать столбец для каждой характеристики (это атрибут) - "размер", "цвет" и т.д.) В EAV-модели все характеристики всех сущностей хранятся в одной таблице из трех столбцов - в первом ID (номер) сущности, во втором номер атрибута, в третьем - его значение. Получается "длинная и худая таблица". При фильтрации, когда мы хотим получить сущность (товар) с определенным атрибутом (характеристикой), то мы объединяем две таблицы - таблицу с товарами и EAV-таблицу, и задаем условие выбора на значение характеристики. Если же нам надо фильтровать по двум характеристикам, мы еще раз добавляем EAV-таблицу в наше объединение, и также задаем для нее условие выбора. Сколько характеристик участвует в выборке - столько раз EAV-таблица и будет добавлена в выборку. Проблема в том, что сложность запроса растет в геометрической прогрессии с каждой добавленной таблицей. Если у нас в таблице 100 строк, то при объединении двух таблиц по 100 строк их будет уже 10000, а при объединении трех - 1000000. Прикиньте, сколько строк в нашей "длинной и худой" таблице, и что случится, если мы фильтруем по пяти-семи характеристикам (и про таблицу с самими товарами не забудьте - она тоже участвует в запросе). Причем, если в других случаях ресурсоемкого запроса мы можем рассчитывать на кэш, поиск и фильтрацию кэшировать по понятным причинам не получится.
    • 24 октября 2014 г. , редакция: 24 октября 2014 г.
    • Цитата
      Есть идея заменить часть характеристик на записи в таблице shop и сортировать напрямую по ней, тогда SQL должен получится легче, но занятие это уж больно долгое.

      Цитата
      - по итогу это получается самое правильное решения, для снижения ресурсоемкости фильтрации. Ну либо надо больше мощных серверов.


      С простыми типами данных(числа, галочки, строки) всё просто.
      Вопрос как реализовать селекты и мультиселекты?
      Ведь именно они дают наибольшую нагрузку БД.
      • 26 октября 2014 г.
      • Цитата
        И возникает вопрос сильно ли помогут при такой проблеме индексы и я правильно понимаю что индексировать следует SHOP_PARAM_ELEMENT и SHOP?

        Добавление индексов вам не поможет, потому что они уже добавлены. Таблица SHOP объединяется с таблицей SHOP_PARAM_ELEMENT с условием shop.id=shop_param_element.element_id, а оба эти поля индексы уже имеют. Если хотите попробовать заняться оптимизацией, то в shop.model в методе list_search_query допишите перед запросом DEV, чтобы увидеть запрос, выполняющийся при поиске, в браузере, а оттуда уже скопируйте его в phpMyAdmin, допишите перед ним EXPLAIN и смотрите, как идет выборка из таблиц, с какими индексами, и прочие подробности. Но вряд ли это спасет отца русской демократии.

        Цитата
        С простыми типами данных(числа, галочки, строки) всё просто. Вопрос как реализовать селекты и мультиселекты? Ведь именно они дают наибольшую нагрузку БД.

        Нет, нагрузку они дают точно такую же, как простые типы. Например, пользователю на сайте предлагается ввести строку, он вводит foo, и потом в запросе накладывается условие value='foo'. В случае с селектом ему будет показан список значений, каждое из которых имеет идентификатор, который и будет отправлен на сервер участвовать в запросе. Скажем, элементы списка 1:foo, 2:bar, пользователь выбирает первое значение, на сервер отправляется 1, в запросе появляется value=1. Ровно то же самое по сути. Кстати, если вы воспользовались первым советом и добавили перед запросом DEV, вы увидите значения, попадающие в запрос. Единственная дополнительная нагрузка - сформировать список и показать пользователю, но это сущие пустяки.
        • 26 октября 2014 г. , редакция: 26 октября 2014 г.
        • Хм. В результате два варианта.
          1. Вынос большей части параметров в таблицу shop.
          2. VPS c SSD.

          Спасибо за подробную информацию(последовал совету и поглядел на запрос и как происходит выборка).

          Ну и возникает вопрос. Как выводить select? В документации не нашёл примеров.
          А хранить думаю можно в виде ENUM.
          • 26 октября 2014 г.
          • Вынос на VPS за 900р в месяц не помог. Вот тариф https://hosting.reg.ru/vps/ssd
            Буду переносить характеристики в таблицу SHOP. Это серьёзно снижает нагрузку на БД(по 30-50мс снижается за один параметр в сложных запросах).
          • 26 октября 2014 г.
          • Цитата
            Ну и возникает вопрос. Как выводить select? В документации не нашёл примеров.
            А хранить думаю можно в виде ENUM.

            Надо будет в shop.admin для каждого поля с селектом делать функцию edit_variable_названиеполя, и в ней формировать html для списка, а значения брать или из таблицы в бд, или руками перечислять, если хотите использовать enum
    • 25 октября 2014 г.
    • Я попробовал представить и у меня от ноликов голова закружилась
      • 26 октября 2014 г.
      • Посмотрите что у вас с индексами таблиц. По умолчанию в Диафане индексов практически нет. Мы у себя на некоторых таблицах по 3-4 индекса добавляли. Для инфо : товаров в базе более 400тыс.
        Также можно отказаться от некоторых условий в WHERE в запросах в модели магазина, например от временных параметров.
        • 26 октября 2014 г. , редакция: 26 октября 2014 г.
        • Индексы для основных таблиц используемых в выборке(shop и shop_param_element) включены.
          Проблема не в количестве товаров, а в кол-ве INNER JOIN. Если их уменьшить в 3 раза запросы начинают летать, без всяких SSD.

          Вот такой запрос на обычном хостинге обрабатывается, 58 секунд.
          Код

          SELECT DISTINCT s.id FROM `diafan_shop` AS s INNER JOIN `diafan_shop_price` AS pr ON pr.good_id=s.id AND pr.trash='0' AND pr.date_start<=1414321401 AND (pr.date_start=0 OR pr.date_finish>=1414321401) AND pr.currency_id=0 AND pr.role_id=0 AND (pr.person='0') INNER JOIN `diafan_shop_param_element` AS pe24 ON pe24.element_id=s.id AND pe24.param_id='24' AND pe24.trash='0' AND pe24.value1='1' INNER JOIN `diafan_shop_param_element` AS pe2 ON pe2.element_id=s.id AND pe2.param_id='2' AND pe2.trash='0' AND pe2.value1 IN (1) INNER JOIN `diafan_shop_param_element` AS pe28 ON pe28.element_id=s.id AND pe28.param_id='28' AND pe28.trash='0' AND pe28.value1<=420 INNER JOIN `diafan_shop_param_element` AS pe9 ON pe9.element_id=s.id AND pe9.param_id='9' AND pe9.trash='0' AND pe9.value1<=100 INNER JOIN `diafan_shop_param_element` AS pe10 ON pe10.element_id=s.id AND pe10.param_id='10' AND pe10.trash='0' AND pe10.value1<=200 INNER JOIN `diafan_shop_param_element` AS pe11 ON pe11.element_id=s.id AND pe11.param_id='11' AND pe11.trash='0' AND pe11.value1<=200 INNER JOIN `diafan_shop_param_element` AS pe12 ON pe12.element_id=s.id AND pe12.param_id='12' AND pe12.trash='0' AND pe12.value1<=100 INNER JOIN `diafan_shop_param_element` AS pe14 ON pe14.element_id=s.id AND pe14.param_id='14' AND pe14.trash='0' AND pe14.value1<=100 INNER JOIN `diafan_shop_param_element` AS pe15 ON pe15.element_id=s.id AND pe15.param_id='15' AND pe15.trash='0' AND pe15.value1<=100 WHERE s.act1='1' AND s.trash='0' AND (s.access='0') AND s.site_id=4 AND s.date_start<=1414357140 AND (s.date_finish=0 OR s.date_finish>=1414357140) GROUP BY s.id, pr.price_id HAVING MIN(ROUND(pr.price))>=3000000 AND MIN(pr.price)<=50000000


          В итоге проблема в запросах функций:
          list_search_query_count и list_search. Которые отчасти дублируют.
          • 26 октября 2014 г. , редакция: 26 октября 2014 г.
          • Ого. А если убрать 3 последних INNER JOIN запрос занимает 0.05 секунды.
            Нашёл описание проблемы http://habrahabr.ru/post/44807/.
            Получается дело в том что каждый JOIN это цикл(то есть циклы в циклах).
          • 30 октября 2014 г.
          • Цитата
            В итоге проблема в запросах функций:
            list_search_query_count и list_search. Которые отчасти дублируют.


            По этому поводу почитайте тут: http://habrahabr.ru/post/64655/

Новости

  • 18 июня
  • В сборке большое обновление demo-шаблона, дополнительная защита от спама, улучшение YML-импорта и еще много важного и интересного.
  • 24 апреля
  • В новой сборке совершили революцию в структурировании кастомизированной информации в шаблонах, добавили авторегистрацию пользователей, усовершенствовали защиту от спама, актуализировали накопительную скидку, а также улучшили производительность и стабильность работы системы.
  • 12 января
  • После выхода сборки 7.1 мы выпустили уже три патча, в каждом из которых улучшаем административную часть сайта. Сборка DIAFAN.CMS 7.1.3 уже доступна к установке. 

Форум