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

标签 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
在检查上述查询的优化器跟踪时。
优化器跟踪成本
  • DUPLICATE-WEEDOUT 策略 - 成本:1.08e7
  • 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

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

    最佳答案

    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/

    相关文章:

    php - 按名称而不是按 2 个日期之间的日期对 sql 请求中的相同行进行排序

    c# - 通过代理服务器连接MySQL

    java - 在java中跨多个数据存储处理事务的方法是什么?

    MySQL从Memory表删除连接InnoDB表

    mysql - 如何优化 MySQL View 的性能

    mysql - 在执行mysqlcheck时Innodb表已损坏,但mysql服务器现在或重新启动时不会崩溃

    php - 如何使用php将隐藏字段数据插入数据库

    mysql - 从 CSV 导入 SQL Server 时如何将日期列的文本数据类型转换为时间戳格式

    sql - 用 parentid 过滤掉表中的 child

    sql - 将表结果合并到列中(数据透视表/交叉表?)