我正在使用MySQL,出于某种原因需要花费大量时间来执行这样的查询:
SELECT
DISTINCT (Movies.id) AS id,
Movies.UnMoID AS UnMoID,
Movies.runtime AS runtime
FROM
Movies
INNER JOIN Acted ON Acted.UnMoID = Movies.UnMoID
INNER JOIN Actors ON Acted.UnMoActorID = Actors.UnMoActorID
INNER JOIN Directed ON Directed.UnMoID = Movies.UnMoID
INNER JOIN Directors ON Directed.UnMoDirectorID = Directors.UnMoDirectorID
WHERE
Actors.name LIKE '%spiderman%'
OR Directors.name LIKE '%spiderman%'
OR Movies.originalTitle LIKE '%spiderman%'
OR Movies.englishTitle LIKE '%spiderman%'
OR Movies.alsoKnownAs LIKE '%spiderman%'
OR Movies.taglines LIKE '%spiderman%'
OR Movies.plot LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20
GROUP BY Movies.id
ORDER BY added DESC
这会让我:“在6.5320秒内执行查询并得到2个结果。”
解释这个特定的查询给出:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Movies ALL UnMoID NULL NULL NULL 925 Using temporary; Using filesort
1 SIMPLE Directed ref UnMoID,UnMoDirectorID UnMoID 62 Movies.Movies.UnMoID 1
1 SIMPLE Directors eq_ref UnMoDirectorID UnMoDirectorID 62 Movies.Directed.UnMoDirectorID 1
1 SIMPLE Acted ref UnMoID,UnMoActorID UnMoID 62 Movies.Movies.UnMoID 34
1 SIMPLE Actors eq_ref UnMoActorID UnMoActorID 62 Movies.Acted.UnMoActorID 1 Using where
概要信息:
......
Creating tmp table 0.000032
Sorting for group 0.000007
executing 0.000005
Copying to tmp table 6.324177
Sorting result 0.000027
Sending data 0.000019
......
在最糟糕的情况下,执行查询最多需要20秒,并且每次大部分时间都转到Copying to tmp table
。那么,我该怎么做才能优化我的查询并获得合理的查询时间。
我有以下索引:
Movies.id PRIMARY
Movies.UnMoID UNIQUE
Movies.runtime INDEX
Acted.UnMoID INDEX
Acted.UnMoActorID INDEX
Actors.UnMoActorID UNIQUE
Actors.name UINDEX
Directed.UnMoID INDEX
Directed.UnMoDirectorID INDEX
Directors.UnMoDirectorID UNIQUE
Directors.name INDEX
Movies.originalTitle INDEX
Movies.englishTitle INDEX
Movies.alsoKnownAs INDEX
Movies.taglines INDEX
Movies.plot INDEX
答案 0 :(得分:2)
索引无法帮助LIKE搜索前导通配符。您可能需要考虑实施full-text search。
答案 1 :(得分:1)
类似搜索的MYSQL非常慢,全文搜索功能仅在MyISAM中可用。您可以尝试使用具有优化索引的读取从属进行优化,但不会获得太多收益。
我会将您的查询移至使用SPHINX或SOLR(data importer for MYSQL)等搜索引擎。
答案 2 :(得分:0)
我认为缓慢的原因是因为你的病情如此广泛。相反,我会尝试制作简单的查询,然后将它们与UNION
结合起来,这也会删除重复项。
所以,这样的事情可能是有益的(我无法真正测试那个声明,因为我没有你的数据库),因为我认为每个个别查询都会非常快,并且合并的记录不会很多:
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added
FROM Movies INNER JOIN Actors ON Acted.UnMoActorID = Actors.UnMoActorID
WHERE Actors.name LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20)
UNION
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added
FROM Movies INNER JOIN Directed ON Directed.UnMoID = Movies.UnMoID
INNER JOIN Directors ON Directed.UnMoDirectorID = Directors.UnMoDirectorID
WHERE Directors.name LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20)
UNION
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added
FROM Movies
WHERE Movies.originalTitle LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20)
UNION
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added
FROM Movies
WHERE Movies.englishTitle LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20)
UNION
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added
FROM Movies
WHERE Movies.alsoKnownAs LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20)
UNION
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added
FROM Movies
WHERE Movies.taglines LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20)
UNION
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added
FROM Movies
WHERE Movies.plot LIKE '%spiderman%'
AND Movies.validated =1
AND Movies.ageCertificate <=20)
ORDER BY added DESC
您需要在查询结果中包含要对其进行排序或过滤的字段。
如果您有一个支持子选择的引擎,您可以将验证和年龄证明的过滤条件从单个查询中移出到公共包装查询中,其中的好处主要是删除重复,因此,维护:
SELECT id, UnMoID, runtime FROM
(SELECT ... ) Q -- the above query including all necessary fields
WHERE Movies.validated =1
AND Movies.ageCertificate <=20
ORDER BY added DESC