关于系统: - 有导师创建课程和包 - 正在遵循基于标签的搜索方法。当新教师注册和教师创建包时(这使得教师和包可搜索),创建了标签关系。有关详细信息,请查看标记在此系统中的工作方式部分?下方。
以下是相关查询
SELECT SUM(DISTINCT( t.tag LIKE "%Dictatorship%" )) AS key_1_total_matches,
SUM(DISTINCT( t.tag LIKE "%democracy%" )) AS key_2_total_matches,
COUNT(DISTINCT( od.id_od )) AS tutor_popularity,
CASE
WHEN ( IF(( wc.id_wc > 0 ), ( wc.wc_api_status = 1
AND wc.wc_type = 0
AND wc.class_date > '2010-06-01 22:00:56'
AND wccp.status = 1
AND ( wccp.country_code = 'IE'
OR wccp.country_code IN ( 'INT' )
) ), 0)
) THEN 1
ELSE 0
END AS 'classes_published',
CASE
WHEN ( IF(( lp.id_lp > 0 ), ( lp.id_status = 1
AND lp.published = 1
AND lpcp.status = 1
AND ( lpcp.country_code = 'IE'
OR lpcp.country_code IN ( 'INT' )
) ), 0)
) THEN 1
ELSE 0
END AS 'packs_published',
td . *,
u . *
FROM tutor_details AS td
JOIN users AS u
ON u.id_user = td.id_user
LEFT JOIN learning_packs_tag_relations AS lptagrels
ON td.id_tutor = lptagrels.id_tutor
LEFT JOIN learning_packs AS lp
ON lptagrels.id_lp = lp.id_lp
LEFT JOIN learning_packs_categories AS lpc
ON lpc.id_lp_cat = lp.id_lp_cat
LEFT JOIN learning_packs_categories AS lpcp
ON lpcp.id_lp_cat = lpc.id_parent
LEFT JOIN learning_pack_content AS lpct
ON ( lp.id_lp = lpct.id_lp )
LEFT JOIN webclasses_tag_relations AS wtagrels
ON td.id_tutor = wtagrels.id_tutor
LEFT JOIN webclasses AS wc
ON wtagrels.id_wc = wc.id_wc
LEFT JOIN learning_packs_categories AS wcc
ON wcc.id_lp_cat = wc.id_wp_cat
LEFT JOIN learning_packs_categories AS wccp
ON wccp.id_lp_cat = wcc.id_parent
LEFT JOIN order_details AS od
ON td.id_tutor = od.id_author
LEFT JOIN orders AS o
ON od.id_order = o.id_order
LEFT JOIN tutors_tag_relations AS ttagrels
ON td.id_tutor = ttagrels.id_tutor
JOIN tags AS t
ON ( t.id_tag = ttagrels.id_tag )
OR ( t.id_tag = lptagrels.id_tag )
OR ( t.id_tag = wtagrels.id_tag )
WHERE ( u.country = 'IE'
OR u.country IN ( 'INT' ) )
AND CASE
WHEN ( ( t.id_tag = lptagrels.id_tag )
AND ( lp.id_lp > 0 ) ) THEN lp.id_status = 1
AND lp.published = 1
AND lpcp.status = 1
AND ( lpcp.country_code = 'IE'
OR lpcp.country_code IN (
'INT'
) )
ELSE 1
END
AND CASE
WHEN ( ( t.id_tag = wtagrels.id_tag )
AND ( wc.id_wc > 0 ) ) THEN wc.wc_api_status = 1
AND wc.wc_type = 0
AND
wc.class_date > '2010-06-01 22:00:56'
AND wccp.status = 1
AND ( wccp.country_code = 'IE'
OR wccp.country_code IN (
'INT'
) )
ELSE 1
END
AND CASE
WHEN ( od.id_od > 0 ) THEN od.id_author = td.id_tutor
AND o.order_status = 'paid'
AND CASE
WHEN ( od.id_wc > 0 ) THEN od.can_attend_class = 1
ELSE 1
END
ELSE 1
END
AND ( t.tag LIKE "%Dictatorship%"
OR t.tag LIKE "%Democracy%" )
GROUP BY td.id_tutor
HAVING key_1_total_matches = 1
AND key_2_total_matches = 1
ORDER BY tutor_popularity DESC,
u.surname ASC,
u.name ASC
LIMIT 0, 20
问题
上述查询返回的结果是正确的(AND逻辑按预期工作),但是对于较重的数据,查询所花费的时间会惊人地增加,而对于当前数据,我认为它与正常查询时间相差25秒大约0.005 - 0.0002秒,这使它完全无法使用。
可能由于所有可能的字段尚未编入索引而导致某些延迟。标记表的标记字段已编制索引。 查询有问题吗? 20多秒执行时间背后的原因是什么?
标签在此系统中的工作方式?
解释查询输出: - 请参阅此屏幕截图 - http://www.test.examvillage.com/Explain_query.jpg
答案 0 :(得分:2)
您可能会看到它是否有助于在以下字段中添加索引:
lptagrels.id_tutor
wtagrels.id_tutor
od.id_author
然后尝试从where子句中删除case-when
结构。
您可以直接添加一些特定于表的限制,例如:left join t2 on t1.id = t2.id AND ...
,以使代码更具可读性。
修改强> 这里似乎有一个错误的方法:搜索所有标签,然后计算与搜索匹配的标签。相反,您应该搜索匹配的标记,然后计算具有这些标记的结果。
答案 1 :(得分:1)
我最近遇到过类似的问题。我不得不修改一个查询来实现一个新功能,这意味着添加几个连接和左连接。逻辑是正确实现的,但它需要一些更大的表格。
解决方案完全重写,正如Brian所说。
我的新方法是这样的:
所有这些都是在存储过程中完成的,最终结果通过了单元测试,而且速度非常快。
<强>更新强>
请测试此查询,以查看它是否返回与原始查询相同的结果。 如果是,那么我将进一步尝试找到更好的实现。
SELECT SUM(DISTINCT( t.tag LIKE "%Dictatorship%" )) AS key_1_total_matches,
SUM(DISTINCT( t.tag LIKE "%democracy%" )) AS key_2_total_matches,
COUNT(DISTINCT( od.id_od )) AS tutor_popularity,
(wc.id_wc > 0
AND wc.wc_api_status = 1
AND wc.wc_type = 0
AND wc.class_date > '2010-06-01 22:00:56'
AND wccp.status = 1
AND ( wccp.country_code = 'IE' OR wccp.country_code IN ( 'INT' ))
) AS 'classes_published',
(lp.id_lp > 0
AND lp.id_status = 1
AND lp.published = 1
AND lpcp.status = 1
AND ( lpcp.country_code = 'IE' OR lpcp.country_code IN ( 'INT' ) )
) AS 'packs_published',
td . *,
u . *
FROM tutor_details AS td JOIN users AS u ON u.id_user = td.id_user
LEFT JOIN order_details AS od ON td.id_tutor = od.id_author
LEFT JOIN orders AS o ON od.id_order = o.id_order
LEFT JOIN learning_packs_tag_relations AS lptagrels ON td.id_tutor = lptagrels.id_tutor --
LEFT JOIN learning_packs AS lp ON lptagrels.id_lp = lp.id_lp
LEFT JOIN learning_packs_categories AS lpc ON lpc.id_lp_cat = lp.id_lp_cat
LEFT JOIN learning_packs_categories AS lpcp ON lpcp.id_lp_cat = lpc.id_parent
LEFT JOIN learning_pack_content AS lpct ON ( lp.id_lp = lpct.id_lp )
LEFT JOIN webclasses_tag_relations AS wtagrels ON td.id_tutor = wtagrels.id_tutor --
LEFT JOIN webclasses AS wc ON wtagrels.id_wc = wc.id_wc
LEFT JOIN learning_packs_categories AS wcc ON wcc.id_lp_cat = wc.id_wp_cat
LEFT JOIN learning_packs_categories AS wccp ON wccp.id_lp_cat = wcc.id_parent
LEFT JOIN tutors_tag_relations AS ttagrels ON td.id_tutor = ttagrels.id_tutor --
JOIN tags AS t ON ( t.id_tag = ttagrels.id_tag )
OR ( t.id_tag = lptagrels.id_tag )
OR ( t.id_tag = wtagrels.id_tag )
WHERE ( u.country = 'IE' OR u.country IN ( 'INT' ) )
AND (NOT ( t.id_tag = lptagrels.id_tag AND lp.id_lp > 0)
or (lp.id_status = 1
AND lp.published = 1
AND lpcp.status = 1
AND ( lpcp.country_code = 'IE' OR lpcp.country_code IN ('INT') )
)
)
AND (not (t.id_tag = wtagrels.id_tag AND wc.id_wc > 0 )
or (
wc.wc_api_status = 1
AND wc.wc_type = 0
AND wc.class_date > '2010-06-01 22:00:56'
AND wccp.status = 1
AND ( wccp.country_code = 'IE' OR wccp.country_code IN ('INT' ) )
)
)
AND (NOT (od.id_od > 0)
OR (
od.id_author = td.id_tutor
AND o.order_status = 'paid'
AND (NOT (od.id_wc > 0) OR od.can_attend_class = 1)
)
)
AND ( t.tag LIKE "%Dictatorship%" OR t.tag LIKE "%Democracy%" )
GROUP BY td.id_tutor
HAVING key_1_total_matches = 1
AND key_2_total_matches = 1
ORDER BY tutor_popularity DESC,
u.surname ASC,
u.name ASC
LIMIT 0, 20
答案 2 :(得分:0)
从后面拿出这个代码并拍摄它。
然后重新开始。
我并不是轻浮,但是这很可怕,你会做自己和其他任何人在未来通过摆脱它而大受欢迎。