我有一个博客文章表,每个博客都有一个外键回到它的作者。有<此表中有15,000个条目。此查询扫描超过19,000行(每EXPLAIN
),需要一个文件排序(可能是常规的MySQL行为),并需要超过400毫秒才能返回5行。可能是因为用于检查项目是否实际发布的复杂WHERE
。
Dearest Stack Overflow,如何控制此查询?
注意:虽然此标准可能需要简化,但所有条件都是必需的。
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` = True AND
`blog_post`.`has_been_fact_checked` = True AND
`blog_post`.`published_date` IS NOT NULL AND
`blog_post`.`published_date` <= '2010-10-25 22:40:05' )
ORDER BY `blog_post`.`published_date` DESC,
`blog_post`.`ordering` ASC,
`blog_post`.`id` DESC
LIMIT 5
除了PK之外,我还有以下索引:
idx_published_blog_post -> blog_post(is_approved, has_been_fact_checked, published_date)
idx_pub_date -> blog_post(published_date)
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
只是执行此查询的代码生成的日期。
非常感谢任何&amp;一切都有帮助!
答案 0 :(得分:5)
MySQL
不支持索引中的ASC/DESC
子句。
您需要创建一个名为reverse_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
你可以摆脱IS NULL
检查,因为不平等条件意味着它。
<强>更新强>
您可能还想阅读这篇文章:
答案 1 :(得分:0)
使用您在query(where子句)中应用的所有条件来查看“blog_post”,并使用此视图直接连接“auth_user”。
如果不清楚,请随意询问。 :)答案 2 :(得分:0)
对我来说,看起来文件可能会扼杀速度。如果您可以将ORDER BY字段放入正在使用的索引中,则可能会提高速度。尝试更改:
idx_published_blog_post - &gt; blog_post(is_approved,has_been_fact_checked,published_date)
到
idx_published_blog_post - &gt; blog_post(is_approved,has_been_fact_checked,published_date DESC,订购ASC,id DESC)
有几个想法:在什么情况下你有一个null published_date,在日期范围内搜索可能会更快? Published_date似乎也是一个日期时间字段,所以在排序时你真的有这样的帖子,你可以每秒发布一次你需要其他排序字段吗?