【问题标题】:mysql join is slow, but where is fastmysql join很慢,但是哪里快
【发布时间】:2013-02-11 00:27:10
【问题描述】:

我在 MySQL 数据库中有 2 个表。 “结果”表有大约 600 万行,包含 3 个内容:值、ID 和不同表中结果名称的 ID。 “结果名称”表包含大约 2000 行。基本上,结果名称包含描述大表中结果的长字符串。

所以,当我想进行查询时,我只是将两个表连接起来,这样我就知道每个结果的名称是什么。

当我尝试加入表格时,问题就来了。如果我像这样进行连接或子查询,它会很慢(连接或子查询大约需要相同的时间):

mysql> select count(analysisresults_id) from analysis_results where result_nameid in (select resultname_id from analysis_resultnames where result_name like '%amygdala%');
+---------------------------+
| count(analysisresults_id) |
+---------------------------+
|                      6436 |
+---------------------------+
1 row in set (18.49 sec)

...但如果我单独执行子查询,它会稍微快一点:

mysql> select count(analysisresults_id) from analysis_results where result_nameid in (13,28);
+---------------------------+
| count(analysisresults_id) |
+---------------------------+
|                      6436 |
+---------------------------+
1 row in set (0.01 sec)

为什么查询时间差异如此之大?为什么子查询被视为常规连接?

【问题讨论】:

  • 问题是什么?硬编码值更快。一个大惊喜。
  • LIKE 比较慢。您可以通过在 result_name 上建立索引来消除这种缓慢,但它不会像直接引用 ID 那样快
  • 我同意 LIKE 很慢,但它只搜索大约 2000 行,并且单独运行该查询是 0.01 秒
  • @GregB,您在上面显示的需要 0.01 秒的查询不包括 LIKE 语句。你能显示这个查询select resultname_id from analysis_resultnames where result_name like '%amygdala%' 需要多长时间吗?
  • 嗨 @Lucas,select resultname_id from analysis_resultnames where result_name like '%amygdala%' 需要 0.01 秒,所以总数应该是 0.02。仍然不到 18 秒 :)

标签: mysql performance join


【解决方案1】:

为什么它不执行子查询 first 并允许使用 ID 键?因为它是DEPENDENT SUBQUERY

尽管子查询实际上似乎并不依赖于外部查询,但 MySQL 会照原样处理它。有多种解决方案,对您来说最简单的可能就是提前获取 ID(因为您已经这样做了)。您似乎也可以使用与子查询相同的 WHERE 子句。

【讨论】:

  • 哇,太棒了。我对这样的行为感到惊讶。我很确定甲骨文不会这样工作。如果是这样,那么这就是两个 rdbms 之间的(另一个)巨大差异。
  • 感谢您的链接。有没有办法在不使用存储过程的情况下使其成为非依赖查询?
  • @GregB 不是我所知道的......这只是 MySQL 似乎做事的方式。我的第二段有一些可能的替代方案。使用单个查询并不总是最好的方法
  • 我发现了更多关于。它被认为是 MySQL 5.x 系列中的一个错误,但它似乎没有被修复:bugs.mysql.com/bug.php?id=25926
  • @GregB 好臭;我以前也遇到过同样的问题。希望他们会在某个时候修复它
【解决方案2】:

字符串匹配代价高:

%amygdala%

必须搜索每个值完全(完全,我的意思是它可以在匹配时短路,但在任何不匹配时都不能)

【讨论】:

  • 第二个查询仍然依赖于字符串匹配。他首先进行字符串匹配以获取 ID。他的问题是为什么一个看似等价的东西要花这么长时间。
  • @ExplosionPills,我听从你的意思,但不要那样阅读 OP。示例代码仅显示了使用 ID 时查询需要多长时间。它不显示运行 2 个单独查询的复合时间。他的问题是为什么一个比另一个花这么多时间。
  • 你应该对他的问题发表评论以澄清
【解决方案3】:

MySQL 有时在优化in 子查询方面做得很差。试试这个:

where exists (select 1
              from analysis_resultnames ar2
              where result_name like '%amygdala%' and
                    ar2.resultname_id = analysis_resultnames = resultname_id
             )

MySQL documentation 很清楚,一个不相关的子查询只计算一次。这意味着您的原始公式将进行全表扫描——这是相当昂贵的。这个公式应该使用索引来获得几千个匹配的行。额外的 like 约束应该很快就会在这个子集上进行。

关于子查询和连接的问题。您将数据库操作“join”与关键字“join”混淆了。在 SQL 中,有几种表示连接的方法。有些人在from 子句中使用诸如“join”之类的关键字。有些在whereselect(甚至having)子句中使用子查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2014-03-15
    • 2012-06-26
    • 2016-12-04
    • 1970-01-01
    • 2015-08-26
    • 2015-05-14
    相关资源
    最近更新 更多