Mic*_*bel 6 mysql performance index query optimization
我需要优化以下查询:
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
Run Code Online (Sandbox Code Playgroud)
EXPLAIN SELECT 给我以下结果:
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
Run Code Online (Sandbox Code Playgroud)
为什么它先是文章,然后是博客文章?是因为博客文章有更多条目吗?以及如何改进查询以便文章帖子可以使用索引?
更新: 在 blogposts.date_created 上设置了索引。删除 blogposts.title LIKE 条件和 date_published <= NOW() 不会做任何事情。
当我删除“ articles.id AS articleid ”时,它可以在文章上使用 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
Run Code Online (Sandbox Code Playgroud)
我仔细查看了该查询,您也许可以重新设计它。我的意思是:
查询的 LIMIT 0,50 部分似乎在最后的查询中变得繁忙。
您可以通过执行以下操作来改进查询的布局:
步骤 1) 创建内联查询以仅收集键。在本例中,是博客帖子的 ID。
步骤 2) 对带有键的内联查询施加任何 WHERE、ORDER BY 和 GROUP BY 子句。
步骤 3) 引入 LIMIT 子句作为进行内联查询的最后一步。
步骤 4) 如果您需要 blogpost 中的其他列作为 blospost 临时表,请将内联查询与 blogpost 表连接起来
步骤 5) 将这个新博客文章与文章表连接起来。
步骤 1-3 旨在创建一个恰好包含 50 行并包含博客文章 ID 的临时表。然后,最后执行所有 JOIN。
将这些步骤应用于您的原始查询后,您应该得到以下结果:
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;
Run Code Online (Sandbox Code Playgroud)
由于您编辑了问题并声明您将删除 LIKE,现在您的查询应该看起来更像这样:
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;
Run Code Online (Sandbox Code Playgroud)
在短语[省略的东西]中,如果除了键之外不需要博客文章中的任何内容,那么您的查询应如下所示:
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;
Run Code Online (Sandbox Code Playgroud)
警告
确保您构建的索引涉及已删除、可见和 date_created 列,如下所示:
ALTER TABLE blogposts ADD INDEX deleted_visible_date_created (deleted,visible,date_created);
Run Code Online (Sandbox Code Playgroud)
试一试 !!!
| 归档时间: |
|
| 查看次数: |
6626 次 |
| 最近记录: |