【问题标题】:MySQL INNER JOIN - '=' vs 'like'MySQL INNER JOIN - '=' vs 'like'
【发布时间】:2012-05-28 13:05:05
【问题描述】:

我们在 MySQL 内部连接方面遇到了一些奇怪的问题。基本上,我们在使用 '=' 运算符时会遇到一个奇怪的错误,但使用 'like' 会使其正常工作。不幸的是,这是通过 ActiveRecord 实现的,没有简单的方法可以直接在其中打“赞”,而且我们想了解这里实际发生的情况。

这是失败的查询:

mysql> SELECT COUNT(*) FROM `versions` INNER JOIN `site_versions`
              ON `versions`.id = `site_versions`.version_id;

这是错误:

ERROR 1296 (HY000): Got error 20008 'Query aborted due to out of query memory'
from NDBCLUSTER

这是有效的查询:

mysql> SELECT COUNT(*) FROM `versions` INNER JOIN `site_versions`
              ON `versions`.id like `site_versions`.version_id;

以下是有关表格本身的一些详细信息:

mysql> desc site_versions;
+----------------------+----------+------+-----+---------+----------------+
| Field                | Type     | Null | Key | Default | Extra          |
+----------------------+----------+------+-----+---------+----------------+
| id                   | int(11)  | NO   | PRI | NULL    | auto_increment |
| version_id           | int(11)  | YES  | MUL | NULL    |                |
[..snip..]
+----------------------+----------+------+-----+---------+----------------+

mysql> desc versions;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
[..snip..]
+------------+--------------+------+-----+---------+----------------+

任何想法为什么“喜欢”有效而“=”无效?

【问题讨论】:

  • 类似的东西真的能给出你期望的结果吗?也许它只是没有加入任何东西(因为对于整数意味着什么?),因此避免了有效查询触发的内存问题。
  • @andrewcooke - 嗯,like 在这样使用时似乎确实有效:sqlfiddle.com/#!2/86792/1
  • 显示每个查询的explain 也可能有助于问题。
  • 我认为您需要包含有关表的数据库引擎的信息。不同选项之间的字符串比较差异很大。
  • 在我看来,您的查询信息量不大,它应该只为您提供 version_id 不为空的 site_versions 的计数,因此不需要加入。你能解释一下你想从数据中知道什么吗?

标签: mysql activerecord inner-join


【解决方案1】:

不确定这是否能解决您的问题,但有可能。不要使用count(*)。也许它对要计算什么感到“困惑”。计算特定字段是最佳实践,例如id。为此,您需要为表使用别名。

SELECT COUNT(v.id) FROM versions as v
INNER JOIN site_versions as sv ON v.id = sv.version_id;

【讨论】:

  • 或者只使用一个常量:SELECT COUNT(1) FROM ...
  • 在像 OP 这样的不寻常情况下,一定不要对您的建议感到太惊讶。我不会。但是这句话,'It's best-practice to count a specific field',是在另一句话的上下文中提出的,即'Don't use count(*)',听起来像是对未来的一般建议,因此至少可以说是有争议的。无论行中的数据或任何其他条件如何,使用COUNT(*) 对组中的行进行计数是完全有效的,并且符合标准。也许在 MySQL 中对它有一些影响,但是你可能不得不提到它是这样的。
  • @Andriy - 我也一直认为应该尽可能避免使用count(*)?虽然语法是有效的并且可能与 op 的问题无关,但确实有a notable difference performance wise。虽然我不是 DBA,但由于这个原因,开发人员总是尽可能避免count(*)。我可能在这里误解了一些东西,如果我理解了,请告诉我。
  • @stefgosselin 有区别,好吧;在您发布的链接中 count(*) 在可空列上优于 count() :)
  • @stefgosselin:嗯,这篇文章确实展示了count(*)count(col) 之间的性能差异,并且差异似乎有利于count(*),除非是我错过了什么.因此,作为开发人员,您可能希望对使用更高效的构造感兴趣,因此我的问题是,为什么要避免使用count(*)
【解决方案2】:

我无法想象like 在这种情况下如何运作良好,但是尝试检查变量MaxAllocate 的值并增加它怎么样?其默认值为32M,最高可增加到1G

参考:http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-ndbd-definition.html#ndbparam-ndbd-maxallocate

【讨论】:

    【解决方案3】:

    具有讽刺意味的是,这似乎与优化有关;通过使用LIKE,您可以强制 MySQL 停止使用可能的索引(至少对于数字列,因为它必须将它们全部转换为字符串以进行比较)。

    因此,通过使用=,MySQL 似乎只是用完了空间(内存/磁盘)来使用索引(检查key_buffer 设置)。

    当然,这只是一种预感,我对 NDB 了解不多,无法进一步帮助您,但我希望这能引导您朝着正确的方向前进。

    【讨论】:

      猜你喜欢
      • 2015-11-29
      • 2012-06-01
      • 1970-01-01
      • 2014-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      相关资源
      最近更新 更多