【问题标题】:Speeding up compliated MySQL query (taking around 15 seconds currently)加速已编译的 MySQL 查询(目前大约需要 15 秒)
【发布时间】:2011-10-23 11:09:27
【问题描述】:

我是索引新手,并没有完全理解它,但是 - 除了主表 - “文章”表(“文章”)之外,我的所有表都使用索引。我没有那么多记录,但查询大约需要 15 秒(显然不可接受)。

我正在使用 CakePHP 构建查询,但我不确定这是否重要。

我试过为slug 做一个索引,为id 做一个索引,为created,rank_id,id,blog 做一个索引

但是 - 它不会使用任何这些。

文章说明表:(添加完整说明)

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

查询:

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`.`site_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

【问题讨论】:

  • 请解释select 命令。
  • 我做到了 - 因此是“文章表的解释:”部分。除非我误会你了?
  • 是的。获取您向我们展示的 select 查询,只需在其前面添加单词 explain - 然后运行。
  • 我。做过。那。你读过我的问题吗?您是否要询问其余的解释数据?
  • 当然,我希望看到完整的解释输出。我没想到你只剪了一行……

标签: mysql join indexing


【解决方案1】:

我不太了解您的数据,但我怀疑您是否需要所有这些左连接。请记住,您可以使用括号来分隔逻辑。例如:

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)

仅使用所需的连接类型时,查询的性能会更好。

【讨论】:

  • 根据我的阅读,CakePHP 不允许嵌套连接——至少在它的语法中,我想保留它——还有其他方法吗?例如 - 我必须做一些事情才能让 Article 表使用索引 - 是/否?
  • @Dave 我认为在这种情况下使用索引非常困难,因为文章表在最左边,WHERE 子句中没有特定于文章的过滤器。
  • WHERE 子句的“Article.id”部分是否足够好?或者 - 即使我不得不放弃为 Article 表建立索引,对加快查询有什么想法吗?
  • @Dave Article.id 在这种情况下是一个连接条件,而不是一个过滤器。通常,如果您连接两个表,其中只有一个使用连接键上的索引。也许您可以将一些连接条件移至 ON 子句,然后在不破坏主要逻辑的情况下从 WHERE 子句中删除 something is NULL 条件。
猜你喜欢
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
相关资源
最近更新 更多