Объединение как подзапрос MySQL

Я хочу оптимизировать запрос, используя объединение в качестве подзапроса. Я не совсем уверен, как построить запрос. Я использую MYSQL 5

Вот исходный запрос:

SELECT  Parts.id 
FROM    Parts_Category, Parts 
    LEFT JOIN Image ON Parts.image_id = Image.id 
WHERE 
( 
    (
        Parts_Category.category_id = '508' OR 
        Parts_Category.main_category_id ='508'
    ) AND 
    Parts.id = Parts_Category.Parts_id 
) AND 
Parts.status = 'A' 
GROUP BY 
    Parts.id 

Что я хочу сделать, так это заменить эту часть ( (Parts_Category.category_id = '508' OR Parts_Category.main_category_id ='508' ) союзом ниже. Таким образом, я могу отказаться от предложения GROUP BY и использовать прямые индексы столбцов, что должно повысить производительность. Таблицы деталей и категорий деталей содержат по полмиллиона записей каждая, так что любой выигрыш будет большим.

(
    SELECT * FROM
    (
        (SELECT Parts_id FROM Parts_Category WHERE category_id = '508') 
        UNION 
        (SELECT Parts_id FROM Parts_Category WHERE main_category_id = '508')
    )
    as Parts_id
)

Может ли кто-нибудь дать мне ключ о том, как переписать его? Я пытался часами, но не могу получить его, так как я новичок в MySQL.


person gus    schedule 21.07.2009    source источник


Ответы (1)


SELECT  Parts.id
FROM    (
        SELECT  parts_id
        FROM    Parts_Category
        WHERE   Parts_Category.category_id = '508'
        UNION
        SELECT  parts_id
        FROM    Parts_Category
        WHERE   Parts_Category.main_category_id = '508'
        ) pc
JOIN    Parts
ON      parts.id = pc.parts_id
        AND Parts.status = 'A'
LEFT JOIN
        Image
ON      image.id = parts.image_id

Обратите внимание, что MySQL может использовать Index Merge, и вы можете переписать свой запрос следующим образом:

SELECT  Parts.id
FROM    (
        SELECT  DISTINCT parts_id
        FROM    Parts_Category
        WHERE   Parts_Category.category_id = '508'
                OR Parts_Category.main_category_id = '508'
        ) pc
JOIN    Parts
ON      parts.id = pc.parts_id
        AND Parts.status = 'A'
LEFT JOIN
        Image
ON      image.id = parts.image_id

, что будет более эффективно, если у вас есть следующие индексы:

Parts_Category (category_id, parts_id)
Parts_Category (main_category_id, parts_id)
person Quassnoi    schedule 21.07.2009
comment
Огромное спасибо Quassnoi. FY1 для категории из 62 000 строк запрос возвращает примерно на 1 секунду быстрее! - person gus; 21.07.2009
comment
Я думаю, что во втором примере мне нужно будет добавить GROUP BY Parts.id, так как мне не нужны дубликаты, в которых часть может быть указана в других категориях. Это была идея использования Union. В любом случае сравню производительность. Еще раз спасибо. - person gus; 21.07.2009
comment
GROUP BY был необходим во втором примере, и если добавить, я получаю ту же проблему - сортировка файлов и использование temp из объяснения. - person gus; 21.07.2009
comment
@John: UNION все еще нужна сортировка файлов. Но вы правы, мне нужно добавить DISTINCT ко второму запросу. - person Quassnoi; 21.07.2009
comment
Спасибо, Quassnoi, я только что добавил DISTINCT в parts_id вместо GROUP BY в Parts.id. как вы сказали - интересно, поясните теперь говорит в доп с помощью Temp и строк требуется 519330? Это было не так, если использовать одиночные индексы для каждого столбца в первом примере. Я перепроверил индексы, и они верны. - person gus; 21.07.2009
comment
@John: ты создал индексы, о которых я писал? Как производительность по запросу? - person Quassnoi; 21.07.2009
comment
Пока тестирую оба. кажется, что они дают разные результаты в зависимости от того, сколько строк задействовано. - person gus; 22.07.2009