【问题标题】:Mysql optimization query on 2 tables2张表上的Mysql优化查询
【发布时间】:2017-12-27 09:15:34
【问题描述】:

让 db1 和 db2 db1.table1

annee   code    code2   var1    ....
1991    11    12    779
1991    11    14    105
1991    11    15    10
1991    12    11    466
1991    12    14    296
1991    12    15    270
1991    14    11    15
1991    14    12    510
1991    14    15    6
1991    15    11    193
1991    15    12    455
1991    15    14    4   
....
1992    11    12    779
1992    11    14    105
1992    11    15    10
1992    12    11    466
1992    12    14    296
1992    12    15    270
1992    14    11    15
1992    14    12    510
1992    14    15    6
1992    15    11    193
1992    15    12    455
1992    15    14    4   
....

db2.table2

var1    code    ...
test  11
test  12
test  14
test2 11
test2 14
test2 15
...

我需要优化以下查询(因为 db1.table1 包含 8 000 000 行):

select annee,sum(var1) from db1.table1 as M where 
M.code in 
(select t1.code from db2.table2 as t1 cross join db2.table2 as t2 where t1.var1='Test2' and t2.var1='Test2' and t1.code <> t2.code) 
and M.code2 in 
(select t2.code from db2.table2 as t1 cross join db2.table2 as t2 where t1.var1='Test2' and t2.var1='Test2' and t1.code <> t2.code) 
group by annee order by annee desc

db1.table1 和 db2.table2 被索引和排序。 任何建议将不胜感激! 谢谢

【问题讨论】:

    标签: mysql select optimization


    【解决方案1】:

    作为变体,您可以尝试以下方法

    select m.annee,sum(m.var1)
    from db1.table1 m
    join
      (
        select t1.code code1,t2.code code2
        from db2.table2 t1
        join db2.table2 t2 on t1.var1='Test2' and t2.var1=t1.var1 and t1.code<t2.code
      ) c
    on (m.code=c.code1 and m.code2=c.code2) or (m.code=c.code2 and m.code2=c.code1)
    group by m.annee
    order by m.annee desc
    

    我用JOIN 代替CROSS JOIN 和JOIN 代替两个IN。

    如果它适合你,你可以尝试优化查询

    select m.annee,sum(m.var1)
    from db2.table2 t1
    join db2.table2 t2 on t1.var1='Test2' and t2.var1=t1.var1 and t1.code<t2.code
    join db1.table1 m on (m.code=t1.code and m.code2=t2.code) or (m.code=t2.code and m.code2=t1.code)
    group by m.annee
    order by m.annee desc
    

    第一个JOIN 返回test2 的所有组合。有 (11,12) 和 (11,14)

    db2.table2 t1
    join db2.table2 t2 on t1.var1='Test2' and t2.var1=t1.var1 and t1.code<t2.code
    

    第二个JOIN 检查来自table1 的这些组合的行

    join db1.table1 m on (m.code=t1.code and m.code2=t2.code) or (m.code=t2.code and m.code2=t1.code)
    

    也尝试检查下一个变体

    select m.annee,sum(m.var1)
    from db2.table2 t1
    join db2.table2 t2 on t1.var1='Test2' and t2.var1=t1.var1 and t1.code<>t2.code
    join db1.table1 m on m.code=t1.code and m.code2=t2.code
    group by m.annee
    order by m.annee desc
    

    如果最后一个变体返回正确的结果,那么您可以尝试将(code,code2) 的索引添加到table1 中

    CREATE INDEX idx_table1_code_code2 ON db1.table1 (code,code2)
    

    【讨论】:

    • 我正在考虑这个。而且我认为它不会给出 OP 所需的结果,因为他们的原始代码正在寻找来自 t1 和 t2 的匹配代码,但不一定来自同一行
    • @Kickstart - 是的,我再次查看查询,我认为你是对的。
    • 我改了答案。
    • m.code = m.code2 = 1 和 db2.table2 和 var1='Test2' 有 2 行代码值为 1 和 2 -> 可以用于询问查询。但是您的查询将消除它,因为t1.code&lt;&gt;t2.code and m.code=t1.code and m.code2=t2.code 将是错误的
    • @KhánhBùiĐức - 是的,我没有考虑这种情况。好的,我会看看。我认为您的更改存在重复行的问题,因为我们有几种组合,其中code1 是相同的。例如11 - (11,12),(11,14),(12,11),(12,14),(14,11),(14,12)。
    【解决方案2】:

    我已尝试让您的查询逻辑更简单。希望对您有所帮助

        select annee,sum(var1) 
            from db1.table1 as M where 
                exists( select var1 from db2.table2 t2 
                            where t2.var1='Test2' 
                            group by t2.var1 
                            having sum(t2.code = M.code) >= 1 
                                and sum(t2.code = M.code2) >= 1 
                                and (M.code != M.code2 or sum(t2.code != M.code) >= 1))
    
            group by annee 
            order by annee desc
    

    【讨论】:

      【解决方案3】:
      table2: INDEX(var1, code)
      table1: INDEX(code, code2, annee)
      

      把IN ( SELECT ... )改成JOIN ( SELECT ... ) ON ...;前者优化不佳。

      如果您使用的是 MySQL 5.6 或更高版本,则子查询可能已得到充分优化。如果您使用的是旧版本,请使用该重复的子查询创建一个 TEMPORARY TABLE。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 2013-06-02
        • 2016-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多