查询2左连接COUNT()需要30秒才能执行

时间:2018-01-27 16:45:11

标签: mysql

我有以下3个表格:

  1. giveaway_steps_done
  2. giveaways_entries
  3. giveaway_steps
  4. giveaway_steps_done

    id      step_unique_alone
    

    giveaways_entries

    id      giveaway_step_unique
    

    giveaway_steps

    id      step_unique_alone
    

    查询列出giveaway_steps的所有记录,然后根据giveaway_steps_done计算step_unique_alone条记录。之后,它会根据giveaways_entries计算giveaway_step_unique条记录。

    SQL查询效果很好,但效果不正确,因为执行和显示需要30秒。

    giveaway_steps_done有7000条记录。 giveaways_entries有6800条记录。 giveaway_steps有170条记录。

    查询:

    SELECT giveaway_steps.*, 
           Count(DISTINCT giveaway_steps_done.id) AS total_steps_count, 
           Count(DISTINCT giveaways_entries.id)   AS total_steps_correct_count 
    FROM   giveaway_steps 
           LEFT JOIN giveaway_steps_done 
                  ON ( giveaway_steps_done.step_unique_alone = 
                       giveaway_steps.step_unique_alone ) 
           LEFT JOIN giveaways_entries 
                  ON ( giveaways_entries.giveaway_step_unique = 
                       giveaway_steps.step_unique_alone ) 
    GROUP  BY giveaway_steps.id 
    ORDER  BY giveaway_steps.id DESC 
    

    样本/预期

    id       (giveaway_steps details)  total_steps_count    total_steps_correct_count 
    1        blabla  3                                      3
    2        blabla  5                                      1
    3        blabla  34                                     22
    4        blabla  52                                     53
    5        blabla  13                                     10
    

    数据是正确的,但需要花费很多时间。我只想做更好的时间/资源消耗查询。

    如何重做问题:

    1. 如上所述创建三个表格。
    2. 如上所述添加cols。
    3. 将10/15条记录添加到giveaway_steps,使用不同的step_unique_alone
    4. 将随机数据添加到其他表格,其step_unique_alone / giveaway_step_unique必须与giveaway_steps中的其中一条记录相匹配。
    5. *问题是,查询需要时间使用LEFT JOIN和COUNT()。

1 个答案:

答案 0 :(得分:1)

此JOIN效率低下,因为它复制了大量数据。

假设giveaway_steps.step_unique_alone是唯一的,giveaway_steps_done.step_unique_alonegiveaways_entries.giveaway_step_unique是引用该列的外键。然后giveaway_steps_done表中有7000/170行,giveaways_entries中每行giveaway_steps有6800/170行。您的JOIN将产生类似(7000/170)*(6800/170)行/"步骤"。总体而言(7000/170)*(6800/170)* 170就像是280K行。但即使有280K行,它也不需要30秒才能执行。所以我猜你错过了支持你加入的索引。

为了避免这个巨大的JOIN,我会计算SELECT子句中子查询中的相关行:

SELECT giveaway_steps.*, 
    (
        SELECT Count(giveaway_steps_done.id)
        FROM giveaway_steps_done
        WHERE giveaway_steps_done.step_unique_alone = giveaway_steps.step_unique_alone
    ) AS total_steps_count,
    (
        SELECT Count(giveaways_entries.id)
        FROM giveaways_entries
        WHERE giveaways_entries.giveaway_step_unique = giveaway_steps.step_unique_alone
    ) AS total_steps_correct_count 
FROM giveaway_steps
ORDER BY giveaway_steps.id DESC

确保您拥有giveaway_steps_done.step_unique_alonegiveaways_entries.giveaway_step_unique上的索引。