这是我的示例查询
Select table1.id
from table1
where table.id in (select table2.id
from table2
where table2.id in (select table3.id
from table3)
)
order by table1.id
limit 100
在检查上述查询的优化器跟踪时。优化器跟踪成本
由于 DUPLICATE-WEEDOUT 成本较低,mysql 对上述查询采取了 DUPLICATE-WEEDOUT 策略。
join_optimization 部分似乎一切都很好。但最后,在检查了 join_execution 部分之后。
DUPLICATE-WEEDOUT 通常会创建临时表。但是这里由于堆大小对于临时表来说是不够的,它继续创建磁盘临时表(converting_tmp_table_to_ondisk)。
由于磁盘临时表,我的查询执行变慢了。
那么这里发生了什么?
优化器跟踪不计算连接优化部分本身的磁盘表成本。如果计算磁盘表成本,它将高于第一次匹配。
那么 final_semijoin_strategy 将是 FIRST-MATCH 策略,这样我的查询会更快。
MYSQL 有什么方法可以计算连接优化部分本身的磁盘表成本或针对此特定问题的任何其他解决方法吗?
MYSQ-5.7, INNODB
注意:这是一个非常动态的查询,其中多个条件将根据查询中的请求添加。所以我已经以所有可能的方式优化了查询。最后还是解决了这个磁盘表成本问题。请避免优化查询(如更改查询结构、强制优先匹配策略)。并且为了增加堆大小(我不太确定,在不同的论坛中很多人说它可能会在其他查询中带来不同的问题)
最佳答案
IN( SELECT ... )
效率低下是出了名的。尽量避免它。
所提出的查询可能等效于
SELECT t1.id
FROM t1
JOIN t2 USING(id)
JOIN t3 USING(id)
ORDER BY id
LIMIT 100
这将很好地优化。这个公式不需要构建任何临时表,更不用说基于磁盘的临时表了。
关于MySQL 优化器 - 成本规划器不知道 DuplicateWeedout 策略何时创建磁盘表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65276645/