如何在MySQL中优化这个速度慢得令人困惑的查询?

如何在MySQL中优化这个速度慢得令人困惑的查询?,mysql,database,optimization,Mysql,Database,Optimization,我有一个博客帖子表,每个帖子都有一个指向作者的外键。此表中有blog\u post(是否已批准、是否已检查事实、发布日期) 到 idx\u已发布\u博客\u帖子->博客\u帖子(是否已批准、是否已检查事实、发布日期描述、订购ASC、id描述) 以下几点思考:在什么情况下发布的日期为空,在日期范围内搜索可能会更快?此外,发布日期似乎是一个日期时间字段,所以在进行排序时,您是否真的有这样的帖子,以便每秒都需要其他排序字段 MySQL不支持索引中的ASC/DESC子句 您需要创建一个名为reverse

我有一个博客帖子表,每个帖子都有一个指向作者的外键。此表中有<15000个条目。此查询扫描19000多行(每个
EXPLAIN
),需要一个文件排序(这可能是MySQL的常规行为),返回5行需要400多毫秒。可能是因为复杂的
,其中
用于检查项目是否实际发布

最亲爱的堆栈溢出,我怎样才能控制这个查询

注意:虽然此标准可能需要简化,但所有条件都是必需的

EXPLAIN
的输出如下所示:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: blog_post
         type: ref
possible_keys: blog_post_author_id,idx_published_blog_post,idx_pub_date
          key: idx_published_blog_post
      key_len: 4
          ref: const,const
         rows: 19856
        Extra: Using where; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: auth_user
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: blog.blog_post.author_id
         rows: 1
        Extra: Using index
2 rows in set (0.00 sec)
旁注:
2010-10-25 22:40:05
只是执行此查询的代码生成的日期

非常感谢您的帮助

查看“blog_post”,查看您在查询(where子句)中应用的所有条件,并直接将“auth_user”与此视图连接起来


如果不清楚,请随时询问。:)

在我看来,文件排序可能会降低速度。如果您可以将ORDER BY字段输入到正在使用的索引中,您可能会获得速度提升。尝试更改:

idx\u发布的\u blog\u post->blog\u post(是否已批准、是否已检查事实、发布日期)

idx\u已发布\u博客\u帖子->博客\u帖子(是否已批准、是否已检查事实、发布日期描述、订购ASC、id描述)


以下几点思考:在什么情况下发布的日期为空,在日期范围内搜索可能会更快?此外,发布日期似乎是一个日期时间字段,所以在进行排序时,您是否真的有这样的帖子,以便每秒都需要其他排序字段

MySQL
不支持索引中的
ASC/DESC
子句

您需要创建一个名为
reverse\u ordering
的单独列,并将其值设置为
-ordering
(前提是
ordering
是一个数值)

然后可以创建以下索引:

CREATE INDEX ix_blogpost_a_c_p_ro_id ON blog_post (is_approved, has_been_fact_checked, published_date, reverse_ordering, id)
并重写您的查询:

SELECT      `blog_post.id`, 
            `blog_post.title`,
            `blog_post.author_id`,
            `blog_post.has_been_fact_checked`,
            `blog_post.published_date`,
            `blog_post.ordering`,
            `auth_user.username`,
            `auth_user.email`
FROM        `blog_post` 
INNER JOIN  `auth_user` 
ON          `blog_post`.`author_id` = `auth_user`.`id`
WHERE       `blog_post`.`is_approved` = 1 AND 
            `blog_post`.`has_been_fact_checked` = 1 AND 
            `blog_post`.`published_date` <= '2010-10-25 22:40:05'
ORDER BY    `blog_post`.`published_date` DESC, 
            `blog_post`.`reverse_ordering` DESC, 
            `blog_post`.`id` DESC 
LIMIT 5
选择'blog\u post.id`,
`blog_post.title`,
`blog\u post.author\u id`,
`博客文章。是否已检查事实,
`博客发布日期`,
`blog_post.ordering`,
`auth_user.username`,
`auth_user.email`
来自“blog_post”
内部联接“auth\u user”
在“blog\u post”上,`author\u id`=`auth\u user`.`id`
其中,`blog\u post`.`is\u approved`=1和
`blog_post`.`是否已检查事实`=1和

`blog_post`.`published_date`如果删除join怎么办?它会改变第一个解释的部分吗?还有-为什么需要“
blog\u post
发布日期
不为空”部分?还有:什么类型的
是批准的,是否检查了
字段<代码>整数
?第一个表中有多少行?有多少记录符合“
blog\u post
发布日期
已批准
已检查
tinyint(1)
fields。几乎所有条目都在
published\u日期内。您是否可以合理地猜测最短日期,从而使
published\u日期
比较成为一个BETWEEN子句?这本身就足够了。在MySQL中,使用视图并不能为您节省大部分时间,因为合并算法是最常用的,它基本上是将请求的语句和视图定义语句拼凑在一起,然后运行结果查询。合并是,所以在这种情况下这不会有帮助。对不起,可以。我不确定你说的是什么。但我在五月的网站上使用过这个过程,它可以加快用户的查询速度。@Carson:canu请按我所说的再试一次。我相信它会提高速度。
MySQL
不支持索引中的
ASC/DESC
。它可能与版本有关,但手册上说4.1和5.0会。我站得住脚了。你可以使用ASC和DESC,但它们被忽略了。尽管如前所述,我认为按日期+时间排序将是b在大多数情况下,这已经足够了
CREATE INDEX ix_blogpost_a_c_p_ro_id ON blog_post (is_approved, has_been_fact_checked, published_date, reverse_ordering, id)
SELECT      `blog_post.id`, 
            `blog_post.title`,
            `blog_post.author_id`,
            `blog_post.has_been_fact_checked`,
            `blog_post.published_date`,
            `blog_post.ordering`,
            `auth_user.username`,
            `auth_user.email`
FROM        `blog_post` 
INNER JOIN  `auth_user` 
ON          `blog_post`.`author_id` = `auth_user`.`id`
WHERE       `blog_post`.`is_approved` = 1 AND 
            `blog_post`.`has_been_fact_checked` = 1 AND 
            `blog_post`.`published_date` <= '2010-10-25 22:40:05'
ORDER BY    `blog_post`.`published_date` DESC, 
            `blog_post`.`reverse_ordering` DESC, 
            `blog_post`.`id` DESC 
LIMIT 5