Speeding up compliated MySQL query (taking around 15 seconds currently)
I'm new to indexing, and don't completely understand it all, but - I have all the tables using an index except for the main one - the 'articles' table ('Article'). I don't have that many records, but the query is taking around 15 seconds (obviously unacceptable).
I'm using CakePHP to build the query, though I'm not sure that matters.
I've tried doing an index for slug
, an index for id
, and an index for created,rank_id,id,blog
But - it won't use any of those.
The Explain for Article table: (added full explain)
1 SIMPLE Article ALL PRIMARY,id 1661 Using temporary; Using filesort
1 SIMPLE Upload ref model, foreign_key model, foreign_key 38 const,myDB.Article.id 10
1 SIMPLE SiteArea const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE SiteAreasSiteSection ref site area id site area id 5 myDB.SiteArea.id 2
1 SIMPLE SiteAreasSiteSubSection ref site area id site area id 5 myDB.SiteArea.id 2
1 SIMPLE SiteSection eq_ref PRIMARY PRIMARY 4 myDB.SiteAreasSiteSection.site_section_id 1 Using index
1 SIMPLE SiteSubSection eq_ref PRIMARY PRIMARY 4 myDB.SiteAreasSiteSubSection.site_sub_section_id 1 Using index
1 SIMPLE RanksSiteArea index all 14 2 Using index
1 SIMPLE ArticlesSiteSection ref site section id site section id 5 myDB.SiteSection.id 244
1 SIMPLE ArticlesSiteSubSection ref site sub section id site sub section id 5 myDB.SiteSubSection.id 28
1 SIMPLE ArticlesSiteArea index all 19 1 Using where; Using index
The Query:
SELECT
Article.title,
GROUP_CONCAT(
`Upload`.`path`,
`Upload`.`name`
ORDER BY
`Upload`.`featured` DESC
)AS Uploads,
`ArticlesSiteArea`.`id`,
`ArticlesSiteArea`.`weight`
FROM
`articles` AS `Article`
LEFT JOIN uploads AS `Upload` ON(
`Article`.`id` = `Upload`.`foreign_key`
AND 'Article' = `Upload`.`model`
)
LEFT JOIN site_areas AS `SiteArea` ON(`SiteArea`.`id` = '1')
LEFT JOIN site_areas_site_sections AS `SiteAreasSiteSection` ON(
`SiteArea`.`id` = `SiteAreasSiteSection`.`开发者_StackOverflowsite_area_id`
)
LEFT JOIN site_areas_site_sub_sections AS `SiteAreasSiteSubSection` ON(
`SiteArea`.`id` = `SiteAreasSiteSubSection`.`site_area_id`
)
LEFT JOIN site_sections AS `SiteSection` ON(
`SiteSection`.`id` = `SiteAreasSiteSection`.`site_section_id`
)
LEFT JOIN site_sub_sections AS `SiteSubSection` ON(
`SiteSubSection`.`id` = `SiteAreasSiteSubSection`.`site_sub_section_id`
)
LEFT JOIN ranks_site_areas AS `RanksSiteArea` ON(
`SiteArea`.`id` = `RanksSiteArea`.`site_area_id`
)
LEFT JOIN articles_site_sections AS `ArticlesSiteSection` ON(
`SiteSection`.`id` = `ArticlesSiteSection`.`site_section_id`
)
LEFT JOIN articles_site_sub_sections AS `ArticlesSiteSubSection` ON(
`SiteSubSection`.`id` = `ArticlesSiteSubSection`.`site_sub_section_id`
)
LEFT JOIN articles_site_areas AS `ArticlesSiteArea` ON(
`ArticlesSiteArea`.`article_id` = `Article`.`id`
)
WHERE
(
(
`ArticlesSiteArea`.`id` IS NOT NULL
)
OR(
(
(`Upload`.`name` <> '')
AND(
(
(
`Article`.`id` = `ArticlesSiteSection`.`article_id`
)
OR(
`ArticlesSiteSection`.`article_id` IS NULL
)
)
)
AND(
(
(
`Article`.`id` = `ArticlesSiteSubSection`.`article_id`
)
OR(
`ArticlesSiteSubSection`.`article_id` IS NULL
)
)
)
AND(
(
(
`RanksSiteArea`.`rank_id` = `Article`.`rank_id`
)
OR(
`RanksSiteArea`.`rank_id` IS NULL
)
)
)
)
)
)
GROUP BY
`Article`.`id`
ORDER BY
`ArticlesSiteArea`.`weight` DESC,
`ArticlesSiteArea`.`id` DESC,
SUBSTR(`Article`.`created`, 1, 10)DESC,
FIELD(`Article`.`rank_id`, 1, 2, 3)DESC
LIMIT 4
I don't know much about your data, but I doubt you need all of these left joins. Keep in mind that you can use parenthesis to separate the logic. For instance:
table1 t1
left join (
table2 t2
inner join table3 t3 on (t3.some_id = t2.some_id)
inner join table4 t4 on (t4.some_id = t3.some_id)
) on (t1.some_id = t2.some_id)
left join table5 t5 on (t5.some_id = t1.some_id)
The query can perform better when you use only the needed join types.
精彩评论