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