尽管使用了 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 所示的索引,但跨数据库查询需要异常长时间才能运行的主要内容,如果未能解决你的问题,请参考以下文章