mysql SQL JOIN查询需要15秒以上才能运行

kwvwclae  于 2023-01-12  发布在  Mysql
关注(0)|答案(2)|浏览(150)

我有一个很大的SQL查询来从多个数据库表中获取数据,我使用ON条件来检查guild_id是否总是相同的,在某些情况下,他还检查user_id。
这就是我的疑问:

SELECT
    SUM( f.guild_id = 787672220503244800 AND f.winner_id LIKE '%841827102331240468%' ) AS guild_winner,
    SUM( f.winner_id LIKE '%841827102331240468%' ) AS win_sum,
    m.message_count,
    r.bypass_role_id,
    i.real_count,
    i.total_count,
    i.bonus_count,
    i.left_count 
FROM
    guild_finished_giveaways AS f
    JOIN guild_message_count AS m
    JOIN guild_role_settings AS r
    JOIN guild_invite_count AS i ON m.guild_id = f.guild_id 
    AND m.user_id = 841827102331240468 
    AND r.guild_id = f.guild_id 
    AND i.guild_id = f.guild_id 
    AND i.user_id = m.user_id

但是它跑得很慢,超过15秒。我不明白为什么它需要这么长时间。
我发现如果我删除了“guild_invite_count”JOIN,它会很快恢复。我是否有一些我没有看到的简单错误?或者是什么问题?

lc8prwob

lc8prwob1#

每个JOIN表达式都需要它自己的ON。不要等到最后再做这个。因为它是,服务器被迫建立所有这些表的笛卡尔积,然后再缩小它们,我很惊讶查询运行了(我以为丢失ON子句会有语法错误)。

FROM guild_finished_giveaways AS f
  JOIN guild_message_count AS m ON m.guild_id = f.guild_id 
  JOIN guild_role_settings AS r ON r.guild_id = f.guild_id
  JOIN guild_invite_count AS i ON i.guild_id = f.guild_id 
      AND i.user_id = m.user_id
WHERE m.user_id = 841827102331240468

在同一个查询中使用SUM()或任何其他聚合函数作为没有GROUP BY子句的非聚合值,这也有点奇怪。

eivgtgni

eivgtgni2#

您使用的是InnoDB吗?
每个表都有一个PRIMARY KEY吗?
这些 * 可能 * 有助于:

m:  PRIMARY KEY(user_id)  -- assuming that is unique in that table
f:  INDEX(guild_id,  winner_id)
r:  INDEX(guild_id,  bypass_role_id)
i:  INDEX(user_id,)

看起来有些表不应该分开--也许r、i、f可以组合在一起?(我需要看一下SHOW CREATE TABLE才能知道更多信息。)
不要在winner_id中有一个commalist。相反,用另一个表,每个游戏的赢家(或任何赢家)占一行。也许只是像一个多对多Map表这样的列。
注意,执行很可能从m开始,然后转到i,让我们改进Joel的建议:

FROM   guild_message_count      AS m
  JOIN guild_invite_count       AS i ON i.user_id  = m.user_id
  JOIN guild_finished_giveaways AS f ON f.guild_id = m.guild_id 
  JOIN guild_role_settings      AS r ON r.guild_id = m.guild_id
WHERE m.user_id = 841827102331240468

注意,在guild_id上连接了3个表;但仅需要2 × 1 m7n1x。
没有GROUP BYSUM对整个结果集求和(JOINing之后)。但是您有6个非聚集,所以您需要对所有6个进行GROUP BY
但这可能会导致严重膨胀的总和。也许你需要做的聚合刚刚超过f * 第一 *,因为这是你求和的地方。然后加入其余的?

相关问题