连接表上的条件比引用条件更快

On *_*und 7 mysql sql join

我有一个涉及两个表的查询:表A有很多行,并包含一个名为的字段b_id,该字段引用表中的记录B,该表有大约30个不同的行.表上A有一个索引b_id,表上B有一个索引name.

我的查询看起来像这样:

SELECT COUNT(A.id) FROM A INNER JOIN B ON B.id = A.b_id WHERE (B.name != 'dummy') AND <condition>;
Run Code Online (Sandbox Code Playgroud)

随着condition桌子上的一些随机条件A(我有很多,所有表现出相同的行为).

此查询非常慢(以2秒为单位),并使用说明,显示查询优化器以表开始,B提供约29行,然后扫描表A.做一个STRAIGHT_JOIN,转动订单,查询立即运行.

我不是黑魔法的粉丝,所以我决定尝试别的东西:拿出B名字的记录的id,dummy比方说23,然后将查询简化为:

SELECT COUNT(A.id) FROM A WHERE (b_id != 23) AND <condition>;
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,这个查询实际上比直接连接要慢,向北走一秒钟.

关于为什么连接比简化查询更快的任何想法?

更新:根据评论中的请求,解释的输出:

直接加入:

+----+-------------+-------+--------+-----------------+---------+---------+---------------+--------+-------------+
| id | select_type | table | type   | possible_keys   | key     | key_len | ref           | rows   | Extra       |
+----+-------------+-------+--------+-----------------+---------+---------+---------------+--------+-------------+
|  1 | SIMPLE      | A     | ALL    | b_id            | NULL    | NULL    | NULL          | 200707 | Using where |
|  1 | SIMPLE      | B     | eq_ref | PRIMARY,id_name | PRIMARY | 4       | schema.A.b_id |     1  | Using where |
+----+-------------+-------+--------+-----------------+---------+---------+---------------+--------+-------------+
Run Code Online (Sandbox Code Playgroud)

没有加入:

+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | A     | ALL  | b_id          | NULL | NULL    | NULL | 200707 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
Run Code Online (Sandbox Code Playgroud)

更新2:尝试了另一种变体:

SELECT COUNT(A.id) FROM A WHERE b_id IN (<all the ids except for 23>) AND <condition>;

这比无连接运行得更快,但仍然比连接慢,所以似乎不等操作负责部分性能命中,但不是全部.

Mos*_*cho 0

也许这应该是评论而不是答案,但会有点长。

首先,很难相信两个具有(几乎)完全相同的解释的查询以不同的速度运行。此外,如果解释中带有额外行的运行速度更快,则这种可能性较小。我想“更快”这个词是这里的关键。

您已经比较了速度(完成查询所需的时间),这是一种极其经验性的测试方法。例如,您可能不正确地禁用了缓存,这使得该比较毫无用处。更不用说您<insert your preferred software application here>在运行测试时可能会发生页面错误或任何其他操作,这可能会导致查询速度降低。

衡量查询性能的正确方法是基于解释(这就是它存在的原因)

因此,我必须回答的最接近的问题是:关于为什么联接比简化查询更快的任何想法?...简而言之,是第 8 层错误。

不过,我确实还有一些其他评论,应该考虑这些评论以加快速度。如果A.id是主键(名字听起来就是这样),根据你的解释,为什么必须count(A.id)扫描所有行?它应该能够直接从索引获取数据,但我Using index在额外的标志中没有看到。看来您甚至没有唯一索引,并且它不是不可为空的字段。这也闻起来很奇怪。确保该字段不为空并且其上有唯一索引,再次运行解释,确认额外标志包含,Using index然后(正确)计时查询。它应该运行得更快。

另请注意,与我上面提到的相同的性能改进方法是将替换count(A.id)count(*).

只是我的2分钱。