librown
@librown
На-все-руки-мастер и немного кодер

JOIN на большой таблицы — как ускорить?

Привет!

Есть таблица товаров (item), таблица брендов (brand) и таблица соответствия товар=бренд (item_brand).
Товаров - 1.5 млн, брендов - 50 тыс.

Сервер: 2 ядра, 4Гб ОЗУ.

Для страницы "фильтра по брендам" делаю такой запрос (на всех полях участвующих в запросе проставил обычные индексы):
SELECT brand.*, count(*) FROM brand 
JOIN item_brand ON item_brand.id_brand = brand.id 
JOIN item ON item.id = item_brand.id_item 
AND item.enabled=1 
AND item.id_category IN (21,317,318) 
GROUP BY brand.id 
ORDER BY count(*) DESC

Один только этот запрос отрабатывает порядка 4-9 секунд. А подобных фильтров на странице еще 5-6. Страница грузится неимоверно долго первый раз (следующие обновления страницы мгновенны из-за кеширования).

Explain:
15f49f17a4.png
Подозреваю что или запросы не правильно строю, или индексы не отрабатывают.
Подскажите, в какую сторону копать?

Вот так фильтр выглядит:
7d0aa2b981.png
Спасибо!
  • Вопрос задан
  • 281 просмотр
Пригласить эксперта
Ответы на вопрос 2
@RoverWhite
У вас один item может иметь отношение с несколькими brand? Если нет тогда линк на бренд в таблицу Item перенести и отказаться от вспомогательной таблицы.
Далее какие индексы на таблице Item присутствуют?
Какой размер у индексов, какие поля Вы включили в индекс?
Если там помимо этого еще хватает таблиц то кеш индексов может переполняться и закешированный с диска индекс вылетит из памяти, и будет при таком обращении перечитываться с диска, а тут уже зависит от скорости диска и размера индекса.
Сделайте EXPLAIN SELECT brand.*, count(*) FROM brand .... на Ваш запрос, посмотрите что происходит....
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
SELECT `b`.`*`, `i`.`count`
  FROM (
    SELECT `ib`.`id_brand` AS `brand`,  COUNT(*) AS `count` 
      FROM `item_brand` AS `ib`
      JOIN `item` AS `i` ON `i`.`enabled` = 1 
        AND `i`.`id_category` IN (21,317,318) 
        AND `i`.`id` = `ib`.`id_item`
      GROUP BY `ib`.`id_brand`
  ) AS `i`
  JOIN `brand` AS `b` ON `b`.`id` = `i`.`id_brand`
  ORDER BY `i`.`count` DESC
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы