我有一个慢的MySQl查询,大约需要15秒才能运行。所以我做了一些调查,发现我可以使用EXPLAIN语句来查看瓶颈在哪里。所以我这样做了,但实际上无法解读这些结果。
如果我不得不采取刺,我会说第一行是一个问题,因为键的值为空。但是,如果是这样,我无法理解为什么classType1表IS在适当的列上编入索引。
有人可以提供一些解释,问题可能在哪里? 非常感谢。
编辑:好的,我已经添加了查询,希望它可以为问题提供更多的亮点。不幸的是,我只是无法向你解释它在做什么,所以如果根据提供的内容提供任何帮助,那就太棒了。
id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, 'PRIMARY', 'classType1', 'system', 'PRIMARY', '', '', '', 1, 'Using temporary; Using filesort'
1, 'PRIMARY', 'user', 'const', 'PRIMARY', 'PRIMARY', '4', 'const', 1, 'Using index'
1, 'PRIMARY', 'class1', 'ref', 'IX_classificationType,IX_classificationValue,IX_classificationObjectType,IX_classificationObjectId', 'IX_classificationObjectId', '8', 'const', 3, 'Using where'
1, 'PRIMARY', 'classVal1', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'ccms.class1.classificationValue', 1, 'Using where; Using index'
1, 'PRIMARY', 'class2', 'ref', 'IX_classificationType,IX_classificationValue,IX_classificationObjectType,IX_classificationObjectId', 'IX_classificationValue', '4', 'ccms.class1.classificationValue', 368, 'Using where'
1, 'PRIMARY', 'album', 'eq_ref', 'PRIMARY,IX_albumType,IX_albumIsDisabled,IX_albumIsActive,IX_albumCSI,IX_albumOwner,IX_albumPublishDate', 'PRIMARY', '4', 'ccms.class2.classificationObjectId', 1, 'Using where'
1, 'PRIMARY', 'profile', 'eq_ref', 'PRIMARY,IX_profileUserId', 'PRIMARY', '4', 'ccms.album.albumOwnerId', 1, 'Using where'
1, 'PRIMARY', 'albumUser', 'eq_ref', 'PRIMARY,IX_userIsAccountPublic', 'PRIMARY', '4', 'ccms.profile.profileUserId', 1, 'Using where'
1, 'PRIMARY', 'photo', 'eq_ref', 'PRIMARY,FK_photoAlbumId', 'PRIMARY', '8', 'ccms.album.albumCoverPhotoId', 1, 'Using where'
2, 'DEPENDENT SUBQUERY', 'class3', 'ref', 'IX_classificationObjectType,IX_classificationObjectId', 'IX_classificationObjectId', '8', 'ccms.class2.classificationObjectId', 1, 'Using where'
3, 'DEPENDENT SUBQUERY', 'class4', 'ref', 'IX_classificationType,IX_classificationValue,IX_classificationObjectType,IX_classificationObjectId', 'IX_classificationObjectId', '8', 'const', 3, 'Using where'
查询是......
SELECT profileDisplayName,albumPublishDate,profileId,albumId,albumPath,albumName,albumCoverPhotoId,photoFilename,fnAlbumGetNudityClassification(albumId) AS albumNudityClassification,fnAlbumGetNumberOfPhotos(albumId,1,0) AS albumNumberOfPhotos,albumDescription,albumCSD,albumUSD,photoId,fnGetAlbumPhotoViewCount(albumId) AS albumNumberOfPhotoViews
FROM user
-- Join User Classifications
INNER JOIN classification class1
ON class1.classificationObjectId = user.userId AND class1.classificationObjectType = 1
INNER JOIN classificationType classType1
ON class1.classificationType = classType1.classificationTypeId
INNER JOIN classificationTypeValue classVal1
ON class1.classificationValue = classVal1.classificationTypeValueId
-- Join Album Classifications
INNER JOIN classification class2
ON class2.classificationObjectType = 3
AND class1.classificationType = class2.classificationType AND class1.classificationValue = class2.classificationValue
INNER JOIN album
ON album.albumId = class2.classificationObjectId
AND albumIsActive = 1
AND albumIsDisabled = 0
LEFT JOIN profile
ON albumOwnerId = profileId AND albumOwnerType = 0
LEFT JOIN user albumUser
ON albumUser.userId = profileUserId
AND albumUser.userIsAccountPublic = 1
LEFT JOIN photo
ON album.albumId = photo.photoAlbumId AND photo.photoId = album.albumCoverPhotoId
WHERE 0 =
(
SELECT COUNT(*)
FROM classification class3
WHERE class3.classificationObjectType = 3
AND class3.classificationObjectId = class2.classificationObjectId
AND NOT EXISTS
(
SELECT 1
FROM classification class4
WHERE class4.classificationObjectType = 1
AND class4.classificationObjectId = user.userId
AND class4.classificationType = class3.classificationType AND class4.classificationValue = class3.classificationValue
)
)
AND class1.classificationObjectId = 8
AND (albumPublishDate <= {ts '2011-01-28 20:48:39'} || albumCSI =
8)
AND album.albumType NOT IN (1)
AND fnAlbumGetNumberOfPhotos(albumId,1,0) > 0
AND albumUser.userIsAccountPublic IS NOT NULL
ORDER BY albumPublishDate DESC
LIMIT 0, 15
答案 0 :(得分:1)
没有看到实际的结构或查询,我会寻找2件事......
我知道你说他们是......但是......确保所有将相应的字段编入索引
示例:您在id_classType1上的字段“active”(仅过滤掉活动记录)和另一个(假设主键索引)的索引...除非您执行唯一索引,类似于此的查询:
SELECT * FROM classType1 WHERE id_classType1 IN (1,2,3) AND active = 1
...需要组合这些索引或单独查找它们。但是,如果你有两个索引,id_classType1和active(并且该索引是一个UNIQUE类型),SQL将使用它并更快地找到组合。
其次,您在EXPLAIN语句中似乎有依赖子查询,这可以单独减慢您的查询速度......请查看此处可能的解决方法:http://forums.mysql.com/read.php?115,128477,128477
我的第一次尝试是用 JOINs 替换这些子查询,然后尝试通过完全删除它们(如果可能)或进行单独查询来进一步优化它那些子查询
这个查询比我见过的任何其他查询都复杂得多,所以请以某些方式提供有限的提示:
这就是所有 - 而且有一个问题:这些表有多少行?不需要确切的数字,只是想看看大约。查询运行的记录数,因为它需要很长时间
答案 1 :(得分:1)
好的,所以通过淘汰过程我找到了问题。
在我的列表中,我接到了一个电话:fnGetAlbumPhotoViewCount(albumId) AS albumNumberOfPhotoViews
在该调用中加入的其中一个表有一个未编入索引的列。很简单。
现在我的问题是,EXPLAIN无法告诉我这一点。如果你看,实际上没有引用EXPLAIN输出中任何位置的页面视图表或列。
那么我可以用什么工具来解决这个问题?
由于