Упрощенно, у меня есть четыре таблицы.
ref_TagGroup (top-level descriptive containers for various tags)
ref_Tag (tags with name and unique tagIDs)
ref_Product
ref_TagMap (TagID,Container,ContainerType)
A fifth table, ref_ProductFamily exists but is not directly part of this query.
Я использую таблицу ref_TagMap для сопоставления тегов с продуктами, а также для сопоставления тегов с группами тегов, а также с семействами продуктов.Для параметра ContainerType установлено значение PROD / TAGGROUP / PRODFAM соответственно.
Итак, я хочу вернуть группу тегов, имя тега и количество продуктов И семейств продуктов, которым сопоставлен тег ... так что результат будет следующим:
GroupName |TagName |TagHitCnt
Мой вопрос: почему первый запрос возвращается в миллисекундах, второй запрос возвращается в миллисекундах, а не в третьем (это просто добавление условия «ИЛИ» для включения тега в продукт и тегана семейные сопоставления) занимает вечность (ну, в любом случае, более десяти минут ... Я не давал ей работать всю ночь.)
QUERY 1:
SELECT ref_taggroup.groupname,ref_tag.tagname,COUNT(DISTINCT IFNULL(ref_product.familyid,ref_product.id + 100000000),ref_product.name) AS 'taghitcnt'
FROM (ref_taggroup,ref_tag,ref_product)
LEFT JOIN ref_tagmap GROUPMAP ON GROUPMAP.containerid=ref_taggroup.groupid
LEFT JOIN ref_tagmap PRODMAP ON PRODMAP.containerid=ref_product.id
WHERE
GROUPMAP.tagid=ref_tag.tagid AND GROUPMAP.containertype='TAGGROUP'
AND
PRODMAP.tagid=ref_tag.tagid AND PRODMAP.containertype='PROD'
GROUP BY tagname
ORDER BY groupname,tagname ;
QUERY 2:
SELECT ref_taggroup.groupname,ref_tag.tagname,COUNT(DISTINCT IFNULL(ref_product.familyid,ref_product.id + 100000000),ref_product.name) AS 'taghitcnt'
FROM (ref_taggroup,ref_tag,ref_product)
LEFT JOIN ref_tagmap GROUPMAP ON GROUPMAP.containerid=ref_taggroup.groupid
LEFT JOIN ref_tagmap PRODFAMMAP ON PRODFAMMAP.containerid=ref_product.familyid
WHERE
GROUPMAP.tagid=ref_tag.tagid AND GROUPMAP.containertype='TAGGROUP'
AND
PRODFAMMAP.tagid=ref_tag.tagid AND PRODFAMMAP.containertype='PRODFAM'
GROUP BY tagname
ORDER BY groupname,tagname ;
QUERY 3:
SELECT ref_taggroup.groupname,ref_tag.tagname,COUNT(DISTINCT IFNULL(ref_product.familyid,ref_product.id + 100000000),ref_product.name) AS 'taghitcnt'
FROM (ref_taggroup,ref_tag,ref_product)
LEFT JOIN ref_tagmap GROUPMAP ON GROUPMAP.containerid=ref_taggroup.groupid
JOIN ref_tagmap PRODMAP ON PRODMAP.containerid=ref_product.id
JOIN ref_tagmap PRODFAMMAP ON PRODFAMMAP.containerid=ref_product.familyid
WHERE
GROUPMAP.tagid=ref_tag.tagid AND GROUPMAP.containertype='TAGGROUP'
AND
((PRODMAP.tagid=ref_tag.tagid AND PRODMAP.containertype='PROD')
OR
(PRODFAMMAP.tagid=ref_tag.tagid AND PRODFAMMAP.containertype='PRODFAM' ))
GROUP BY tagname
ORDER BY groupname,tagname ;
- Чтобы ответить на вопрос, который может возникнуть, в отчете COUNT Distinct ifnull предназначен для возврата одной записи для большого числа продуктов, которыесгруппированы по семьям и по одной записи для каждого «отдельного» продукта, которого нет в семье.Этот код хорошо работает в других запросах.
Я пытался выполнить UNION для первых двух запросов, и это работает и возвращается очень быстро, но это не практично по другим причинам, в которые я не буду вдаватьсяздесь.
Каков наилучший способ сделать это?Что я делаю не так?
Спасибо!
ДОБАВЛЕНИЕ ОБЪЯСНЕНИЯ ВЫХОДА
QUERY1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE GROUPMAP ALL 5640 Using where; Using temporary; Using filesort
1 SIMPLE ref_tag ref PRIMARY PRIMARY 4 lsslave01.GROUPMAP.tagid 1 Using index
1 SIMPLE ref_taggroup ref PRIMARY PRIMARY 4 lsslave01.GROUPMAP.containerid 3 Using index
1 SIMPLE PRODMAP ALL 5640 Using where; Using join buffer
1 SIMPLE ref_product eq_ref PRIMARY PRIMARY 4 lsslave01.PRODMAP.containerid 1
QUERY2
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE GROUPMAP ALL 5640 Using where; Using temporary; Using filesort
1 SIMPLE ref_tag ref PRIMARY PRIMARY 4 lsslave01.GROUPMAP.tagid 1 Using index
1 SIMPLE ref_taggroup ref PRIMARY PRIMARY 4 lsslave01.GROUPMAP.containerid 3 Using index
1 SIMPLE PRODFAMMAP ALL 5640 Using where; Using join buffer
1 SIMPLE ref_product ref FixtureType FixtureType 5 lsslave01.PRODFAMMAP.containerid 39 Using where
QUERY3
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE GROUPMAP ALL 5640 Using where; Using temporary; Using filesort
1 SIMPLE ref_tag ref PRIMARY PRIMARY 4 lsslave01.GROUPMAP.tagid 1 Using index
1 SIMPLE ref_taggroup ref PRIMARY PRIMARY 4 lsslave01.GROUPMAP.containerid 3 Using index
1 SIMPLE PRODMAP ALL 5640 Using join buffer
1 SIMPLE PRODFAMMAP ALL 5640 Using where; Using join buffer
1 SIMPLE ref_product eq_ref PRIMARY,FixtureType PRIMARY 4 lsslave01.PRODMAP.containerid 1 Using where
enter code here
Еще одно обновление для всех, кто интересуется: я наконец-то позволилтретий запрос выше выполняется до завершения.Это заняло около 1000 секунд.Разделив это время на время выполнения каждого из запросов (1 или 2), мы получим число около 6000 ... что очень близко к размеру таблицы ref_tagmap, которую мы используем в нашей среде разработки (намного больше в производстве).Итак, похоже, что мы выполняем один запрос к каждой записи в этой таблице ... но я до сих пор не понимаю, почему.
Любая помощь будет высоко ценится ... и я имею в виду серьезно, серьезнооценили.