我需要优化下查询:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM blogposts
JOIN articles ON articles.blogpost_id = blogposts.id
WHERE blogposts.deleted = 0
AND blogposts.title LIKE '%{de}%'
AND blogposts.visible = 1
AND blogposts.date_published <= NOW()
ORDER BY blogposts.date_created DESC
LIMIT 0 , 50

解释选择,让我以下结果:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE articles ALL blogpost_id NULL NULL NULL 6915 Using temporary; Using filesort
1 SIMPLE blogposts eq_ref PRIMARY PRIMARY 4 articles.blogpost_id 1 Using where

为什么首先把文章和随后的博客?这是因为博客有多个条目?和我如何可以改善查询,以便的articlepost可以使用的一个指数?

更新: 一个指标是设在博客.date_created.除去的博客.标题,如条件和date_published <=NOW()没有做任何事情。

当我删除了"文章。id作为民遭受"它可以使用blogpost_id索引的文章...听起来很奇怪我,别人知道为什么吗?(因为实际上我需要它..)

新的解释 看起来是这样的:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  articles    index blogpost_id blogpost_id    4    NULL    6915    Using index; Using temporary; Using filesort
1   SIMPLE  blogposts   eq_ref  PRIMARY PRIMARY 4   articles.blogpost_id    1   Using where
有帮助吗?

解决方案

我仔细看看查询并可能可以重新设计。这里是我的意思是:

限制需0,50部分的查询似乎是由繁忙的在查询最后一个。

你可以改善布局的查询通过执如下:

步骤1)创建一个内联的查询,以收集只键。在这种情况下,身份证对于博客.

步骤2)规定任何在那里,以便通过和组通过的条款在线查询带来的钥匙。

步骤3)关税的限制条款作为最后的步骤使在线查询。

步骤4)加入在线查询与博文表在该事件中,你需要额外的列从博文为,应升级授权表,使之blostpost

步骤5)中加入这个新的博客,应升级授权表,使之与本条款表。

步骤1-3的是创建一个应升级授权表,使之与完全50行和包括博文id。然后,执行所有加入死的最后一次。

这些步骤应用到你原来的查询,你应该有这样的:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
  SELECT B.*
  FROM
  (
    SELECT id FROM blogposts
    WHERE date_published <= NOW()
    AND deleted = 0 AND visible = 1
    AND title LIKE '%{de}%'
    ORDER BY date_created DESC
    LIMIT 0,50
  ) A
  INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;

因为你编的问题,并指出,将删除一样,现在你的查询应该看起来更像这样:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
  SELECT B.*
  FROM
  (
    SELECT id FROM blogposts
    WHERE date_published <= NOW()
    AND deleted = 0 AND visible = 1
    ORDER BY date_created DESC
    LIMIT 0,50
  ) A
  INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;

一语中的[东西省略],如果你什么都不需要从其他博客比键,然后您的查询应该是这样的:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
  SELECT id FROM blogposts
  WHERE date_published <= NOW()
  AND deleted = 0 AND visible = 1
  ORDER BY date_created DESC
  LIMIT 0,50
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;

警告

确保建立一个指数涉及的列有删除,可见,date_created如下:

ALTER TABLE blogposts ADD INDEX deleted_visible_date_created (deleted,visible,date_created);

给它一试试!

其他提示

你在那里的条件 blogposts.title LIKE '%{de}%' 会造成一个完整的表格的扫描的 博客 表。它是可能的MySQL数字扫描第6915文章更加有效。

如何来改善它,可能会添加一个索引 博客 使用 date_createddate_published 并添加一个范围内到那里条件(比其他的东西 <=NOW())

和博客.标题LIKE'%{de}%' --无用的优化(导致野卡)

那里的博客.删除=0 和博客.visible=1 --好:如果他们不应当显示,获得他们的表格。

和博客.date_published <=NOW() 为了通过博客.date_created DESC 限制0,50 -这导致了需要索引(date_published) (但是,像和标志可以防止这种指数从被使用。)

请提供 显示CREATE TABLE...;显示表的状态...;

非常感谢你:)

我给它一试发现,实际上你的最后评论的有关指数的东西我需要的。有时这只是一些小的改进,这是需要...;) 比较:

旧的查询:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM blogposts
JOIN articles ON articles.blogpost_id = blogposts.id
WHERE blogposts.deleted = 0
AND blogposts.title LIKE '%{de}%'
AND blogposts.visible = 1
AND blogposts.date_published <= NOW()
ORDER BY blogposts.date_created DESC
LIMIT 0 , 50

新的查询:

SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
    SELECT B.*
    FROM
    (
        SELECT id FROM blogposts
        WHERE date_published <= NOW()
        AND deleted = 0 AND visible = 1
        AND title LIKE '%{de}%'
        ORDER BY date_created DESC
        LIMIT 0,50
    ) A
    INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id

现在没有该索引提及:

老解释的结果:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE articles ALL blogpost_id NULL NULL NULL 6915 Using temporary; Using filesort
1 SIMPLE blogposts eq_ref PRIMARY PRIMARY 4 articles.blogpost_id 1 Using where

新的解释的结果:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    50   
1   PRIMARY     articles    ref     blogposts_id    blogposts_id    4   blogposts.id    1    
2   DERIVED     <derived3>  ALL     NULL    NULL    NULL    NULL    50   
2   DERIVED     B   eq_ref  PRIMARY     PRIMARY     4   A.id    1    
3   DERIVED     blogposts   ALL     deleted,visible,date_published  deleted     1       28198   Using filesort

解释的结果与指数上的老查询:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  blogposts   ref     PRIMARY,deleted,visible,date_published,deleted_vis...   deleted_visible_date_created    2   const,const     27771   Using where
1   SIMPLE  articles    ref     blogposts_id    blogposts_id    4   db.blogposts.id     1

解释的结果与索引新的查询:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    50   
1   PRIMARY     articles    ref     blogposts_id    blogposts_id    4   blogposts.id    1    
2   DERIVED     <derived3>  ALL     NULL    NULL    NULL    NULL    50   
2   DERIVED     B   eq_ref  PRIMARY     PRIMARY     4   A.id    1    
3   DERIVED     blogposts   ref     deleted,visible,date_published,deleted_visible_dat...   deleted_visible_date_created    2       27771   Using where

速度在旧的查询,而无需用指数: 0.1835/0.0037

速度在新的查询,而无需用指数: 0.1883/0.0035

因为只是边际differency之间的旧的新的查询,我喜欢仍然使用旧的查询,但有的指标。但是我将记住这一点,因为如果有一天老的查询是太慢:)

什么是有趣的,我知道,你怎么有这个想法设置指这样吗?我认为,我发表这个问题,我还试图与deleted_visible但不是date_created我用date_published(因为它在那里的条款)...

谢谢:)

更新通过RolandoMySQLDBA2011-05-19 13:03

什么把它放到我是在哪里和秩序的条款。

在其中的条款,删除(0)和可见(1)是静态的价值观。在通过条款,date_created是喜欢移动的目标之间的所有行删除=0和visible=1个。所以,我放的静态变量在前面的索引,然后再运动目标的最后指标。通常,这一部分的基本原则重构SQL发言。你需要的索引,将支持你在哪里,小组通过的,并以条款。

许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top