优化 mysql 查询以减少搜索的行数

Posted

技术标签:

【中文标题】优化 mysql 查询以减少搜索的行数【英文标题】:optimise a mysql query to reduce rows searched 【发布时间】:2019-11-08 16:52:47 【问题描述】:

我目前正在抓取我网站上发布的最后 5 个 cmets,我认为这似乎做得很糟糕。

这是 SQL 查询:

SELECT c.comment_id
     , c.article_id
     , c.time_posted
     , a.title
     , a.slug
     , u.username
  FROM articles_comments c 
  JOIN articles a 
    ON c.article_id = a.article_id 
  JOIN users u 
    ON u.user_id = c.author_id 
 WHERE a.active = 1 
   AND c.approved = 1 
 ORDER 
    BY c.comment_id DESC 
 LIMIT 5 

我的问题是,必须搜索很多行,这似乎很浪费。我很好奇是否有更好的方法。

这是对它的解释的输出:

如您所见,它给出的行数是 81,486,这看起来有点搞笑。我在这里错过了什么?

【问题讨论】:

也许这会有所帮助:explainextended.com/2009/10/23/… 如果您只需要获取最后 5 个 cmets,为什么需要 JOINarticles AND users 表? @Eric 所以它可以显示评论所在的文章名称和评论者的用户名。 【参考方案1】:

结果,只是强制articles_cmets 使用PRIMARY 键(comment_id)作为INDEX 修复它。

问题是我的排序选择了所有已批准的 cmets,因此它使用已批准的列进行排序,导致它从数万个中选择数据。

【讨论】:

对未来的另一个考虑。你有 Time_Posted。如果您有大量活动,您甚至可以通过添加… AND Time_Posted > 2 天前来缩短更多时间…除非是一个非常低容量的网站,否则你知道你的活动…那么它就不必再回去了远非如此(前提是时间发布也是一个索引选项)。还要查看 mysql“STRAIGHT_JOIN”子句,它告诉引擎……按照我布置的确切顺序进行查询。不要猜测我的加入条件以获得最佳处理。 不知道 STRAIGHT_JOIN,非常感谢!也会记住这一点。【参考方案2】:
c:  INDEX(approved, comment_id)  -- in this order
a:  I assume you have PRIMARY KEY(article_id)
u:  I assume you have PRIMARY KEY(user_id)

希望c 索引能够处理一些WHERE,以及ORDER BYLIMIT。最坏的情况是它必须扫描整个表而不找到 5 行。

81,486 是假的。以下是获取优质信息的准确方法:

FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';

“读取”将指示有多少行数据和索引被触及;写入指示正在使用临时表。

【讨论】:

以上是关于优化 mysql 查询以减少搜索的行数的主要内容,如果未能解决你的问题,请参考以下文章

Mysql优化

MySQL---查询性能优化

计算日期范围内每个日期的行数

优化 MySQL 查询以进行整数范围搜索

MySQL ISAM 搜索优化

MySQL--查询性能优化