我们的某个网站上的搜索引擎非常慢。我打开了慢查询日志并记录了所有超过10秒的查询。 仅记录来自此搜索引擎的查询。 以下是日志的一个示例:
# Time: 120801 9:21:42
# User@Host: ********** @ localhost []
# Query_time: 22.156250 Lock_time: 0.000000 Rows_sent: 33 Rows_examined: 3385401
SET timestamp=1343805702;
SELECT *, IF(InSection OR InBranche, 1, 0) AS SorteerKolom FROM(SELECT DISTINCT Plant, Email, Nicename, Displayname, JobTitle, Department, Initials, Lastname, LastnameForSort,
search_people.ForeignId, IsVennoot,
(Zoekwoorden LIKE '%statutair%') AS SearchTerm,
(Displayname LIKE '%statutair%') AS ByName,
0 AS InSection, 0 AS InBranche, 1 AS ShowAll,
(SELECT COUNT(*) FROM search_hasarticles WHERE UserId = search_people.ForeignId) > 0 AS HasWritten
FROM search_people
LEFT JOIN search_people_branches ON search_people.ForeignId = search_people_branches.UserId
LEFT JOIN search_people_specialismen ON search_people.ForeignId = search_people_specialismen.UserId
LEFT JOIN wp_usermeta AS wpu ON (wpu.user_id = search_people.ForeignId)
WHERE
(
Firstname LIKE '%statutair%'
OR Lastname LIKE '%statutair%'
AND Displayname LIKE '%statutair%'
OR Email LIKE '%statutair%'
OR Address LIKE '%statutair%'
OR Initials LIKE '%statutair%'
OR Location LIKE '%statutair%'
OR Givenname LIKE '%statutair%'
OR Nickname LIKE '%statutair%'
OR JobTitle LIKE '%statutair%'
OR Login LIKE '%statutair%'
OR Title LIKE '%statutair%'
OR Phone LIKE '%statutair%'
OR Fax LIKE '%statutair%'
OR Plant LIKE '%statutair%'
OR Displayname LIKE '%statutair%'
OR Zoekwoorden LIKE '%statutair%'
)
AND (1=1) AND search_people.IsHidden = 0 AND search_people.Activated = 1 UNION SELECT DISTINCT Plant, Email, Nicename, Displayname, JobTitle, Department, Initials, Lastname, LastnameForSort,
search_people.ForeignId, IsVennoot, 0 AS SearchTerm, 0 AS ByName, 0 AS InSection, 1 AS InBranche, 1 AS ShowAll,
(SELECT COUNT(*) FROM search_hasarticles WHERE UserId = search_people.ForeignId) > 0 AS HasWritten
FROM search_people
LEFT JOIN search_people_branches ON search_people.ForeignId = search_people_branches.UserId
LEFT JOIN search_branches ON search_branches.ForeignId = search_people_branches.BrancheId
LEFT JOIN search_people_specialismen ON search_people.ForeignId = search_people_specialismen.UserId
WHERE Name LIKE '%statutair%' AND (1=1) AND search_people.IsHidden = 0 AND search_people.Activated = 1 UNION SELECT DISTINCT Plant, Email, Nicename, Displayname, JobTitle, Department, Initials, Lastname, LastnameForSort, search_people.ForeignId, IsVennoot, 0 AS SearchTerm, 0 AS ByName, 1 AS InSection, 0 AS InBranche, 1 AS ShowAll, (SELECT COUNT(*) FROM search_hasarticles WHERE UserId = search_people.ForeignId) > 0 AS HasWritten FROM search_people LEFT JOIN search_people_specialismen ON search_people.ForeignId=search_people_specialismen.UserId LEFT JOIN search_specialties ON search_specialties.ForeignId=search_people_specialismen.SpecialismeId LEFT JOIN search_people_branches ON search_people.ForeignId=search_people_branches.UserId WHERE (Name LIKE '%statutair%' OR SearchTerms LIKE '%statutair%') AND (1=1) AND search_people.IsHidden = 0 AND search_people.Activated = 1 UNION SELECT DISTINCT Plant, Email, Nicename, Displayname, JobTitle, Department, Initials, Lastname, LastnameForSort, search_people.ForeignId, IsVennoot, 0 AS SearchTerm, 0 AS ByName, 0 AS InSection, 0 AS InBranche, 0 AS ShowAll, 1 AS HasWritten FROM search_posts LEFT JOIN search_posts_branches ON search_posts.ForeignId=search_posts_branches.PostId LEFT JOIN search_branches ON search_posts_branches.BrancheId=search_branches.ForeignId LEFT JOIN search_people_specialismen ON search_posts.PostAuthor=search_people_specialismen.UserId LEFT JOIN search_specialties ON search_people_specialismen.SpecialismeId=search_specialties.ForeignId INNER JOIN search_people ON search_people.ForeignId=search_posts.PostAuthor WHERE (PostTitle LIKE '%statutair%' OR PostContent LIKE '%statutair%' OR search_branches.Name LIKE '%statutair%' OR search_specialties.Name LIKE '%statutair%') AND PostStatus='publish' AND PostType='post' AND (1=1) AND search_people.IsHidden = 0 AND search_people.Activated = 1) AS search_results ORDER BY SearchTerm DESC, ByName DESC, SorteerKolom DESC, IsVennoot DESC, InSection DESC, InBranche DESC, HasWritten DESC, LastnameForSort ASC, Initials ASC;
正如您所看到的,查询大约需要22秒才能执行,如果在MySQL中直接执行相同的查询则需要大约4秒钟。
我在同一个查询上做了一个EXPLAIN,uotput如下:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 33 Using filesort
2 DERIVED search_people ALL NULL NULL NULL NULL 323 Using where; Using temporary
2 DERIVED search_people_branches ALL NULL NULL NULL NULL 2013 Distinct
2 DERIVED search_people_specialismen ALL NULL NULL NULL NULL 1013 Distinct
2 DERIVED wpu ref user_id user_id 8 wordpress.search_people.ForeignId 84 Using index; Distinct
3 DEPENDENT SUBQUERY search_hasarticles ALL NULL NULL NULL NULL 101 Using where
4 UNION search_branches ALL NULL NULL NULL NULL 19 Using where; Using temporary
4 UNION search_people ALL NULL NULL NULL NULL 323 Using where; Using join buffer
4 UNION search_people_specialismen ALL NULL NULL NULL NULL 1013 Distinct
4 UNION search_people_branches ALL NULL NULL NULL NULL 2013 Using where; Distinct; Using join buffer
5 DEPENDENT SUBQUERY search_hasarticles ALL NULL NULL NULL NULL 101 Using where
6 UNION search_specialties ALL NULL NULL NULL NULL 73 Using where; Using temporary
6 UNION search_people ALL NULL NULL NULL NULL 323 Using where; Using join buffer
6 UNION search_people_specialismen ALL NULL NULL NULL NULL 1013 Using where; Distinct; Using join buffer
6 UNION search_people_branches ALL NULL NULL NULL NULL 2013 Distinct
7 DEPENDENT SUBQUERY search_hasarticles ALL NULL NULL NULL NULL 101 Using where
8 UNION search_posts ALL NULL NULL NULL NULL 15860 Using where; Using temporary
8 UNION search_posts_branches ALL NULL NULL NULL NULL 149 Distinct
8 UNION search_branches ALL NULL NULL NULL NULL 19 Distinct
8 UNION search_people_specialismen ALL NULL NULL NULL NULL 1013 Distinct
8 UNION search_specialties ALL NULL NULL NULL NULL 73 Using where; Distinct
8 UNION search_people ALL NULL NULL NULL NULL 323 Using where; Distinct; Using join buffer
UNION RESULT <union2,4,6,8> ALL NULL NULL NULL NULL NULL
有人可以解释为什么同样的查询在我的网站上然后直接在MySQL中慢得多吗?或者更重要的是,有没有办法在这个网站上加快查询速度?
如果您需要更多信息进行故障排除,请大声说出来,我会尝试提供这些信息。
非常感谢, 一月
这是查询的PROFILE:
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000431 |
| Opening tables | 0.002004 |
| System lock | 0.000012 |
| Table lock | 0.000502 |
| optimizing | 0.000033 |
| statistics | 0.000042 |
| preparing | 0.000034 |
| Creating tmp table | 0.000085 |
| executing | 0.000004 |
| Copying to tmp table | 0.001957 |
| Sending data | 0.000006 |
| optimizing | 0.000025 |
| statistics | 0.000027 |
| preparing | 0.000041 |
| Creating tmp table | 0.000114 |
| executing | 0.000001 |
| Copying to tmp table | 0.000058 |
| Sending data | 0.000004 |
| optimizing | 0.000021 |
| statistics | 0.000027 |
| preparing | 0.000037 |
| Creating tmp table | 0.000095 |
| executing | 0.000003 |
| Copying to tmp table | 0.007376 |
| optimizing | 0.000013 |
| statistics | 0.000017 |
| preparing | 0.000011 |
| executing | 0.000005 |
| Sending data | 0.001248 |
| executing | 0.000014 |
| Sending data | 0.001894 |
| executing | 0.000007 |
| Sending data | 0.003249 |
| executing | 0.000004 |
| Sending data | 0.001487 |
| executing | 0.000001 |
| Sending data | 0.000433 |
| executing | 0.000001 |
| Sending data | 0.012100 |
| executing | 0.000006 |
| Sending data | 0.000713 |
| executing | 0.000002 |
| Sending data | 0.000681 |
| executing | 0.000001 |
| Sending data | 0.015382 |
| executing | 0.000005 |
| Sending data | 0.001048 |
| executing | 0.000002 |
| Sending data | 0.000916 |
| executing | 0.000004 |
| Sending data | 0.000421 |
| executing | 0.000001 |
| Sending data | 0.000561 |
| executing | 0.000001 |
| Sending data | 0.005126 |
| executing | 0.000008 |
| Sending data | 0.014534 |
| executing | 0.000004 |
| Sending data | 0.001666 |
| executing | 0.000006 |
| Sending data | 0.001641 |
| Sending data | 0.000203 |
| optimizing | 0.000045 |
| statistics | 0.000050 |
| preparing | 0.000049 |
| Creating tmp table | 0.000182 |
| executing | 0.000002 |
| Copying to tmp table | 5.101209 |
| Sending data | 0.000226 |
| optimizing | 0.000007 |
| statistics | 0.000008 |
| preparing | 0.000007 |
| executing | 0.000001 |
| Sending data | 0.000217 |
| removing tmp table | 0.000044 |
| Sending data | 0.000007 |
| removing tmp table | 0.000012 |
| Sending data | 0.000017 |
| removing tmp table | 0.000011 |
| Sending data | 0.000005 |
| removing tmp table | 0.000033 |
| Sending data | 0.000008 |
| removing tmp table | 0.000030 |
| Sending data | 0.000009 |
| init | 0.000044 |
| optimizing | 0.000005 |
| statistics | 0.000004 |
| preparing | 0.000007 |
| executing | 0.000002 |
| Sorting result | 0.000074 |
| Sending data | 0.000164 |
| end | 0.000003 |
| query end | 0.000005 |
| freeing items | 0.000210 |
| removing tmp table | 0.000061 |
| closing tables | 0.000051 |
| logging slow query | 0.000003 |
| cleaning up | 0.000026 |
+----------------------+----------+
答案 0 :(得分:2)
我看到很多不可索引的条件,例如Firstname LIKE '%statutair%'
。一种可能性是MySQL实际上正在使用其results cache,而PHP无法利用结果缓存。例如,如果您将PDO与ATTR_EMULATE_PREPARES option disabled一起使用,就会发生这种情况。
要找到答案,请在MySQL中进行测试时添加SQL_NO_CACHE子句,如:
SELECT SQL_NO_CACHE id, name FROM customer;
答案 1 :(得分:0)
在我看来,你必须在很多列上设置一个索引。请阅读:http://dev.mysql.com/doc/refman/5.0/en/explain-output.html 要使查询更快,首先要在JOIN语句中使用的每一列上设置索引。如果这不会加快速度,请在您检查WHERE的列上设置索引。 此外,OR运算符很慢,并且在具有所有OR的块中还存在AND。也许你可以跳过其中的一些OR,比如'姓名缩写'(但这当然是个猜测......)