我的查询很慢。我在3张桌子之间搜索。 Se_movies = 80000条记录,se_movie_contenttags = 1.6 mil记录,se_movie_descriptiontags -200000条记录
两个简化查询。
或 - 慢速
SELECT SQL_NO_CACHE count(movie_id)
FROM se_movies LEFT JOIN se_users ON se_movies.movie_user_id=se_users.user_id
LEFT JOIN
(
SELECT did , cid , ifnull(cid,did) as uid FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
LEFT JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
ON dtag.did=ctag.cid
UNION
SELECT did , cid , ifnull(cid,did) as uid FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
RIGHT JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
ON dtag.did=ctag.cid
)
AS tagobjects ON se_movies.movie_id=tagobjects.uid
WHERE ( se_movies.movie_title LIKE '%dog%') **OR** ( (cid IS NOT NULL or did IS NOT NULL) and uid IS NOT NULL )
AND - 快速
SELECT SQL_NO_CACHE count(movie_id)
FROM se_movies LEFT JOIN se_users ON se_movies.movie_user_id=se_users.user_id
LEFT JOIN
(
SELECT did , cid , ifnull(cid,did) as uid FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
LEFT JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
ON dtag.did=ctag.cid
UNION
SELECT did , cid , ifnull(cid,did) as uid FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
RIGHT JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
ON dtag.did=ctag.cid
)
AS tagobjects ON se_movies.movie_id=tagobjects.uid
WHERE ( se_movies.movie_title LIKE '%dog%') **AND** ( (cid IS NOT NULL or did IS NOT NULL) and uid IS NOT NULL )
每个人
( se_movies.movie_title LIKE '%dog%') - around 300
(cid IS NOT NULL or did IS NOT NULL) and uid IS NOT NULL - return 595
但如果他们中的任何人返回50或更少,那就很快。
基本上,如果任何关键字在每个标签和电影表标题中都超过500,则需要60秒
否则为2.3秒
有更好的方法吗?
我知道你们可以在这两者之间做UNION ...... 和其他东西......和
搜索 - 标题OR(contenttag或desctag)
问题是查询的变化太多......
如果数据在两个不同的表中,它是否有问题?无论如何加速他们?。
感谢。
系统 - mysql apache2 php5 ubuntu - amazon aws。
解释 enter link description here
通过
解决SELECT SQL_NO_CACHE count(movie_id) FROM se_movies LEFT JOIN se_users ON se_movies.movie_user_id = se_users.user_id 内部联接 (SELECT tag_object_id AS movieid FROM se_movie_contenttags WHERE tag_name IN('dog') 联盟 SELECT tag_object_id AS movieid FROM se_movie_descriptiontags WHERE tag_name IN('dog') 联盟 SELECT s1.movie_id AS movieid FROM se_movies as s1 WHERE s1.movie_title LIKE'%dog%' 联盟 SELECT s2.movie_id AS movieid FROM se_movies as s2 WHERE s2.movie_desc LIKE'%dog%' ) AS tagobjects ON se_movies.movie_id = tagobjects.movieid
.5sec
答案 0 :(得分:0)
如果se_movie_descriptiontags
和se_movie_contenttags
包含(movie_id, tag)
对并且您想要包含所有包含特定代码的电影,我会将tagobjects
内嵌视图替换为:
SELECT `tag_object_id` AS `uid` FROM `se_movie_descriptiontags`
WHERE `tag_name` IN ('dog')
UNION
SELECT `tag_object_id` FROM `se_movie_contenttags`
WHERE `tag_name` IN ('dog')
此查询将返回在se_movie_descriptiontags
和se_movie_contenttags
表中的任何一个或两个中都带有“dog”标签的电影ID。然后你可以在主查询中删除OR ((cid IS NOT NULL OR did IS NOT NULL) AND uid IS NOT NULL)
。
最终的完整查询将是:
SELECT SQL_NO_CACHE count(movie_id)
FROM
se_movies LEFT JOIN
se_users ON se_movies.movie_user_id=se_users.user_id INNER JOIN
(
SELECT `tag_object_id` AS `uid` FROM `se_movie_descriptiontags`
WHERE `tag_name` IN ('dog')
UNION
SELECT `tag_object_id` FROM `se_movie_contenttags`
WHERE `tag_name` IN ('dog')
) AS tagobjects ON se_movies.movie_id=tagobjects.uid
WHERE (se_movies.movie_title LIKE '%dog%')
另外,请注意(se_movies.movie_title LIKE '%dog%')
单独是性能杀手,因为无法使用movie_title
列上的索引对其进行优化,并且肯定会导致表扫描。这主要是因为条件以通配符开头。对于这种情况,我建议研究MySQL的全文搜索功能。