开发者

MySQL EXPLAIN output explanation

I have a slow MySQl query that takes about 15 seconds to run. So I did some investigation and discovered I can use the EXPLAIN statement to see where the bottleneck is. So I did that, but really can't decipher these results.

If I had to take a stab, I would say the first line is a problem as there are null values for the keys. However, if that is so, I can't understand why as the classType1 table IS indexed on the appropriate columns.

Could someone please offer some explanation as to where the problems might lay? Thanks so much.

EDIT: Ok, I have added the query as well hoping that it might offer some more light to the issues. Unfortunately I just won't be able to explain to you what it's doing, so if any help could be offered based on what's provided, that would be great.

   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'

Query is...

SELECT   profileDisplayName,albumPublishDate,profileId,albumId,albumPath,albumName,albumCoverPhotoId,photoFilename,fnAlbumGetNudityClassification(albumId) AS albumNudityClassification,fnAlbumGetNumberOfPhotos(albumId,1,0) AS albumNumberOfPhotos,albumDescription,albumCSD,albumUSD,photoId,fnGetAlbumPhotoVie开发者_如何学JAVAwCount(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


without seeing the actual structure or query, I would look for 2 things...

I know you said they are... but... make sure all the appropriate fields are indexed

example: you have an index on field "active" (to filter out only active records) and another one (let's say primary key index) on id_classType1... unless you do a unique index on "id_classType1, active", a query similar to this:

SELECT * FROM classType1 WHERE id_classType1 IN (1,2,3) AND active = 1

... would need to either combine those indexes or look them up separately. However, if you have an index on both, id_classType1 AND active (and that index is a type UNIQUE), SQL will use it and find the combinations much quicker.


secondly, you seem to have dependent subqueries in your EXPLAIN statement, which can alone slow your query down quite a lot... have a look here for a possible workaround: http://forums.mysql.com/read.php?115,128477,128477

my first try would be to replace those subqueries by JOINs and then perhaps try to optimize it further by removing them altogether (if possible) or making a separate queries for those subqueries


EDIT

this query is more complex that any other I've ever seen, so take these as somehow limited tips:

  • try removing subqueries (just put anything you know will work and give results there temporarily)
  • I see a lot of INNER JOINS in the query, which can be quite slow, as they need to join all rows from both tables (source: http://dev.mysql.com/doc/refman/5.0/en/join.html) - maybe there's a way to replace them somehow?
  • also - and this is something I remember from the past (might not be true or relevant) - shouldn't WHERE-like statements be in the WHERE clause, not the JOIN clause? for example, I would put the following from the 1st JOIN into a WHERE section: class1.classificationObjectType = 1

that's just about all - and one question: how many rows do those table have? no need for exact numbers, just trying to see on approx. how many records the query runs, as it takes so long


Ok ,so through process of elimination I managed to find the issue.

In my column list, I had a call: fnGetAlbumPhotoViewCount(albumId) AS albumNumberOfPhotoViews

One of the tables joined in that call had a column that was not indexed. Simple enough.

Now my question is, EXPLAIN could not show me that. If you look, there is in fact no reference to the pageview table or columns anywhere in the EXPLAIN output.

So what tool could I have used to weed out this issue??

Thanks

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜