Как правильно создать фасетный велосипед?

Добрый день,

в одном из проектов начал отлавливать тяжелые запросы в связи с поиском по каталогу в котором более 10 000 позиций и куча вариантов фильтрации.

Проект работает на "Битрикс - Старт" без умного фильтра и фасетных индексов.

Условия тестирования скорости запроса для Битрикса:
Фильтр: для CIBlockElement::GetList
$arFilter = array(
        'IBLOCK_ID'               => '8',
        'PROPERTY_district'       => $params['district'],
        '><PROPERTY_area'         => array($params['area_from'], $params['area_to']),
        '><PROPERTY_price_total'  => array($params['price_from'], $params['price_to']),
        'PROPERTY_deal'           => $params['deal'],
        'PROPERTY_rooms'          => $params['rooms'],
        '><PROPERTY_floor'        => array($params['floor_from'], $params['floor_to']),
        'PROPERTY_is_new'         => $params['building_new'] == '1' ? 'true' : 'false',
        '><PROPERTY_floors_total' => array($params['floors_from'], $params['floors_to']),
        'PROPERTY_city'           => $params['city'],
    );

Выбор полей: array('IBLOCK_ID', 'ID')


Тестируемый запрос без кеша возвращает результат за 3.49609804153 сек.

Условия тестирования скорости запроса для вспомогательной таблицы:
Запрос: по тем же полям (столбцам) и значениям за исключением IBLOCK_ID
SELECT * FROM `filter_values` WHERE (`district` IN ('...')) OR (`area` BETWEEN '...' AND '...') OR `is_new` = 'false' OR 
...
// Столбцы id | element_id | district | area | is_new | ...

Выбор полей: *

Второй запрос для CIBlockElement::GetList:
$arFilter = array(
        'IBLOCK_ID' => '8',
        'ID'    => $arIds,
    );

Выбор полей: array('IBLOCK_ID', 'ID')


За счет создания отдельной таблицы, в которой содержится ID элемента и его свойства в столбцах по которым может происходить фильтрация, удалось получить ID элементов за 0.107703924179 сек.
Далее полученные ID передаются в GetList, который отрабатывает за 0.911054849625 сек.

Используя свой велосипед удается добиться того же результата за 1 сек.

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

Спасибо.
  • Вопрос задан
  • 378 просмотров
Пригласить эксперта
Ответы на вопрос 1
gromdron
@gromdron
Работаю с Bitrix24
Ваше решение вполне имеет место быть, а грабли будут те же самые, что и в Битриксе - перестроение кеша.
Например у Вас добавилось поле, а это значит, что Вам нужно перестраивать кеш (т.е. удалять и заново строить), а на работающем сайте это занимает прилично времени.
К тому же, для ускорения Вам придется либо исключить некоторые поля, либо дублировать записи из множественных списков, но с этим частично может помочь разгрузка базы.

На ум приходят две мысли:
- при mysql 5.7+ можно проверить как поведет себя json поля (чтобы не пересобирать каждый раз схему, а просто переписывать значения)
- попробовать вынести куда-нибудь на mongodb это решение (дописывать поля там, не пересобирая).

Но в целом, Ваш вариант вполне подходит (за исключением того, что вариант с перестроением кеша нужно все-таки проработать).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы