尽管使用了 EXPLAIN 所示的索引,但跨数据库查询需要异常长时间才能运行

Posted

技术标签:

【中文标题】尽管使用了 EXPLAIN 所示的索引,但跨数据库查询需要异常长时间才能运行【英文标题】:Cross database query takes abnormaly long to run despite using indices as shown by EXPLAIN 【发布时间】:2014-06-20 13:52:24 【问题描述】:
Table_A
id int(11)
sku varchar(24)
Total number of records 250000, sku indexed

Table_B
id int(11)
sku varchar(16)

Total number of records - 180000, sku indexed

以下查询已运行超过 30 分钟

Select count(*) 
from Table_A 
where not exists(select 1 from Table_B where Table_B.sku = Table_A.sku)

同时 select count(*) from Table_B where exists(select 1 from Table_A where Table_A.sku = Table_B.sku) 不到一秒就执行完毕。

有人能解释一下会发生什么吗?

忘了说Table_A和Table_B在不同的数据库中

mysql> 描述 db1.table_a; +------------+-------------+------+-----+--------- +-------+ |领域 |类型 |空 |钥匙 |默认 |额外 | +------------+-------------+------+-----+--------- +-------+ |产品编号 |整数(11) |否 |优先级 |空 | | |货号 | varchar(24) |是 |穆尔 |空 | | +------------+-------------+------+-----+--------- +-------+ 2 行(0.00 秒) mysql> 描述 db2.table_b; +-------+-------------+------+-----+---------+---- ---+ |领域 |类型 |空 |钥匙 |默认 |额外 | +-------+-------------+------+-----+---------+---- ---+ |斯诺|整数(11) |否 |优先级 |空 | | |货号 | varchar(24) |是 |穆尔 |空 | | +-------+-------------+------+-----+---------+---- ---+ 2 行(0.00 秒) mysql> 解释 select count(*) from db2.table_b where not exists(select 1 from db1.table_a where table_a.sku = table_b.sku); +----+--------+---------+--------+----- ----------+------+---------+------+--------+------ ------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+--------+---------+--------+----- ----------+------+---------+------+--------+------ ------------------+ | 1 |初级 |表_b |索引 |空 |货号 | 27 |空 | 181286 |使用哪里;使用索引 | | 2 |依赖子查询 |表_a |参考 |货号 |货号 | 75 |功能 | 1 |使用哪里;使用索引 | +----+--------+---------+--------+----- ----------+------+---------+------+--------+------ ------------------+ 2 行(0.00 秒) mysql> 解释 select count(*) from db1.table_a where not exists(select 1 from db2.table_b where table_b.sku = table_a.sku); +----+--------+---------+--------+----- ----------+------+---------+------+--------+------ ------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+--------+---------+--------+----- ----------+------+---------+------+--------+------ ------------------+ | 1 |初级 |表_a |索引 |空 |货号 | 75 |空 | 277030 |使用哪里;使用索引 | | 2 |依赖子查询 |表_b |索引 |空 |货号 | 27 |空 | 181286 |使用哪里;使用索引 | +----+--------+---------+--------+----- ----------+------+---------+------+--------+------ ------------------+ 2 行(0.00 秒)

【问题讨论】:

尝试解释那个查询 依赖子查询不是很好,尝试以@Notulysses sugestst的身份加入解决方案 也许蜜蜂的问题应该是,你在第一个表中有sku,声明为varchar(24),在第二个表中声明为varchar(16) 感谢大家的回复。问题在于排序规则,它们是不同的。更改了排序规则,查询在大约 2 秒内完成。 @a5995 感谢您分享您的发现,如果 MySQL 必须在 JOIN 条件下转换编码/排序规则,这似乎是一个很可能的解释。这还可以解释我在导入 MySQL 转储时遇到的类似行为。我最终以不同的方式重新导入数据并且问题得到了解决,所以我不再关心,但根本原因可能是相同的。实际上,我强烈认为您应该将其发布为您自己问题的答案并接受它,因为它肯定会对将来进行跨数据库查询的其他人有所帮助。 【参考方案1】:

在 MySQL 中LEFT JOIN 应该比NOT EXISTS 有更好的性能:

SELECT COUNT(a.*) 
FROM Table_A a LEFT JOIN Table_B b ON a.sku = b.sku
WHERE b.sku IS NULL

【讨论】:

也试过这个,但即使这个查询运行了半个多小时。不知道是什么原因导致了这种延迟。【参考方案2】:

正如建议将其发布为答案。 发现问题出在排序规则上。将表的排序规则更改为相同,查询在大约 2 秒内完成。

【讨论】:

以上是关于尽管使用了 EXPLAIN 所示的索引,但跨数据库查询需要异常长时间才能运行的主要内容,如果未能解决你的问题,请参考以下文章

如何判断索引是否生效--explain

PHPUnit 错误“未定义的索引:HTTP_HOST”

nodejs MongoDB 索引 和 explain 的使用(11)

mysql explain的使用

MongoDB 索引 和 explain 的使用

MongoDB 索引 和 explain 的使用