2014-02-15 5 views
0

У нас есть электронный магазин, и в этом электронном магазине существует множество сложных связей между категориями и продуктами.Slow Mysql Query with 3 left join

Я использую таблицу таксономии, чтобы хранить отношения между продуктами-категориями и продуктами-продуктами в качестве субпродукта.

Продукты могут быть членами более чем одной категории. Продукты могут быть субпродуктом субпродуктом другого продукта. (Может быть больше, чем один) Продукты могут быть модулем из другого продукта (может быть больше, чем один)

псевдонимами запроса: пр-продукта кт Категория зр-Sub Продукт мкр-модуль

Select pr.*,ifnull(sp.destination_id,0) as `top_id`, 
    ifnull(ct.destination_id,0) as `category_id` 
from Products as pr 
Left join Taxonomy as ct 
    on (ct.source_id=pr.id and ct.source='Products' and ct.destination='Categories') 
Left join Taxonomy as sp 
    on (sp.source_id=pr.id and sp.source='Products' and sp.destination='Products' and sp.type='TOPID') 
Left join Modules as md 
    on(pr.id = md.product_id) 
where pr.deleted=false 
    and ct.destination_id='47' 
    and sp.destination_id is null 
    and md.product_id is null 
order by pr.order,pr.sub_order 

С данным запросом; Я пытаюсь получить все продукты под Category_id = 47, а не модуль любого продукта, а не субпродукт любого продукта.

Этот запрос длится 23 секунд. Существует 7,820 записей в продуктах, 3.200 записей в модулях и 19.000 записей в таксономии

ответ

0

Я собирался сказать, что MySQL может использовать только один индекс для каждого запроса, но похоже, что это уже не так. Я также наткнулся на это в другом ответе: http://dev.mysql.com/doc/mysql/en/index-merge-optimization.html

Однако это может не помочь вам.

В прошлом, когда я сталкивался с запросами, MySQL не мог оптимизировать. Я решил разрешить ответы в другой таблице с использованием фонового задания.

То, что вы пытаетесь сделать, выглядит как подходящее для базы данных графа, например neo4j.

0

Оптимизатор MySQL, как известно, плохо меняет внешний интерфейс Outer to Inner, сначала выполняет внешнее соединение, а затем начинает фильтровать данные.

В вашем случае соединение между продуктами и таксономией может быть переписано как внутренняя запись (есть условие WHERE на ct.destination_id = '47 ').

Попробуйте, если это изменит план выполнения и улучшит производительность.