MySQL 优化器 - 成本规划器不知道 DuplicateWeedout 策略何时创建磁盘表

vin*_*eth 6 mysql sql innodb sql-execution-plan

这是我的示例查询

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
Run Code Online (Sandbox Code Playgroud)

在检查上述查询的优化器跟踪时。优化器跟踪成本

  1. DUPLICATE-WEEDOUT 策略 - 成本:1.08e7
  2. FIRST MATCH 策略 - 成本:1.85e7

由于 DUPLICATE-WEEDOUT 成本较低,mysql 对上述查询采取了 DUPLICATE-WEEDOUT 策略。

join_optimization 部分似乎一切都很好。但最后,在检查了 join_execution 部分之后。DUPLICATE-WEEDOUT 通常会创建临时表。但是这里由于堆大小不足以容纳临时表,它继续创建磁盘临时表(converting_tmp_table_to_ondisk)。

由于磁盘临时表,我的查询执行变慢了。


那么这里发生了什么?

优化器跟踪不计算连接优化部分本身的磁盘表成本。如果计算磁盘表成本,它将高于第一次匹配。那么 final_semijoin_strategy 将是 FIRST-MAT​​CH 策略,这样我的查询会更快。

MYSQL 有什么方法可以计算连接优化部分本身的磁盘表成本或针对此特定问题的任何其他解决方法吗?

MYSQ-5.7, INNODB


注意:这是一个非常动态的查询,其中多个条件将根据查询中的请求添加。所以我已经以所有可能的方式优化了查询。最后还是解决了这个磁盘表成本问题。请避免优化查询(如更改查询结构、强制优先匹配策略)。并且为了增加堆大小(我不太确定,在不同的论坛中很多人说它可能会在其他查询中带来不同的问题)

Ric*_*mes 0

IN( SELECT ... )一直是出了名的低效。尽量避免它。

如所呈现的,该查询可能相当于

SELECT  t1.id
    FROM  t1
    JOIN  t2 USING(id)
    JOIN  t3 USING(id)
    ORDER BY  id
    LIMIT  100
Run Code Online (Sandbox Code Playgroud)

这会很好地优化。

此公式不需要构建任何临时表,更不用说基于磁盘的临时表了。