MySQL 随意选择是否执行查询

MySQL chooses to execute queries, or not, at whim

对于报告输出,我曾经删除并重新创建 table 'mis.pr_approval_time'。但现在我只是截断它。

用数据填充上面的 table 之后,我 运行 一个 UPDATE 语句,但我已经把它写成下面的 SELECT...

SELECT t.account_id FROM mis.hj_approval_survey h INNER JOIN mis.pr_approval_time t ON h.country = t.country AND t.scheduled_at =
(
    SELECT MAX(scheduled_at) FROM mis.pr_approval_time 
    WHERE country = h.country 
    AND scheduled_at <= h.created_at 
    AND TIME_TO_SEC(TIMEDIFF(h.created_at, scheduled_at)) < 91
);

当我运行上面的语句甚至只是...

SELECT t.account_id FROM mis.hj_approval_survey h INNER JOIN mis.pr_approval_time t ON h.country = t.country AND t.scheduled_at =
(
    SELECT MAX(scheduled_at) FROM mis.pr_approval_time 
    WHERE country = h.country
);

...它 运行 永远不会结束。 hj_approval_survey table 中只有约 3,400 行,pr_approval_time 中只有 29,000 行。我 运行 在具有 15+ GB RAM 的 Amazon AWS 实例上执行此操作。

现在,如果我简单地右键单击 pr_approval_time table 并选择 ALTER TABLE 选项,然后不做任何事情就关闭,那么上面的查询 运行秒。

我想当我触发 ALTER TABLE 选项并且 Workbench 填充 table 字段时,它可能以某种方式改进了它的执行计划,但我不确定为什么。有没有人遇到过类似的事情?如何在不右键单击 table 并选择 'ALTER TABLE'

的情况下触发更好的执行计划检查

编辑

值得一提的是,我的组织也使用 DOMO。最初,我将此设置作为 DOMO 上的 MySQL 数据流,但查询在大多数情况下都无法完成,但我观察到它有时会完成。

这就是我将此查询移回我们的 AWS MySQL RDS 的原因。所以这个问题不仅在我们自己的 MySQL RDS 上观察到了,而且可能在 DOMO

上也观察到了

假设您在连接涉及的列上有适当的索引 您可以尝试使用按子查询分组并加入国家

来重构您的查询
  SELECT t.account_id 
  FROM mis.hj_approval_survey h 
  INNER JOIN mis.pr_approval_time t ON h.country = t.country 
  INNER JOIN (
    SELECT country, MAX(scheduled_at)  max_sched
        FROM mis.pr_approval_time 
        group by country
    ) z on z.contry = t.country and t.scheduled_at = z.max_sched

我怀疑这很慢,因为相关的子查询(子查询取决于来自父 table 的行值,这意味着它必须对每一行执行)。我会尝试稍微修改 pr_approval_time table 所以它是 point-in-time 然后你可以使用 JOIN 来选择正确的行而不用做相关的子查询。类似于:

SELECT
    hj_approval_survey.country
,   hj_approval_survey.created_at
,   pr_approval_time.account_id
FROM
    @hj_approval_survey AS hj_approval_survey
JOIN    (
            SELECT
                current_row.country
            ,   current_row.scheduled_at AS scheduled_at_start
            ,   COALESCE( MIN( next_row.scheduled_at ), GETDATE() ) AS scheduled_at_end
            FROM
                @pr_approval_time AS current_row
            LEFT OUTER JOIN
                @pr_approval_time AS next_row ON (
                    next_row.country = current_row.country
                AND next_row.scheduled_at > current_row.scheduled_at
                )
            GROUP BY
                current_row.country
            ,   current_row.scheduled_at
        ) AS pr_approval_pit ON (
            pr_approval_pit.country = hj_approval_survey.country
        AND (   hj_approval_survey.created_at >= pr_approval_pit.scheduled_at_start
            AND hj_approval_survey.created_at < pr_approval_pit.scheduled_at_end
            )
        )
JOIN    @pr_approval_time AS pr_approval_time ON (
            pr_approval_time.country = pr_approval_pit.country
        AND pr_approval_time.scheduled_at = pr_approval_pit.scheduled_at_start
        )
WHERE
        TIME_TO_SEC( TIMEDIFF( hj_approval_survey.created_at, pr_approval_time.scheduled_at ) ) < 91