开发者

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.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜