Mysql left join with nested select慢,如何优化

Posted

技术标签:

【中文标题】Mysql left join with nested select慢,如何优化【英文标题】:Mysql left join with nested select slow, how to optimize 【发布时间】:2021-08-01 00:47:50 【问题描述】:

我有一个执行速度很慢的 LEFT JOIN mysql 查询,我正在寻找改进。 我有一个表“VM”列出了“VmId”(+ 一些其他数据)和另一个表“VM_Status”列出了 VM 的状态(上/下),每一行都有一个“inputDate”。

表 VM 为 7.000 行,表 VM_Status 为 76.000 行

我需要选择 7.000 VM 的最新状态

我的查询如下,执行需要 25 秒:

SELECT 
VM.*,
`VM_Status`.`Status` AS `Status`
FROM VM
left join (
   select
       * 
   from
       `VM_Status` `s1`
   where
       (
           `s1`.`InputDate` = (
               select
                   max(`s2`.`InputDate`)
               from
                   `VM_Status` `s2`
               where
                   (`s1`.`VmId` = `s2`.`VmId`)
           )
       )

) `VM_Status` on(
   (
       `VM_Status`.`VmId` = `WORKLOAD`.`VmId`
   )
)

我怎样才能更快地做到这一点?

【问题讨论】:

查看添加的标签。 【参考方案1】:

您可以使用窗口函数。Window Functions in MySQL

MySQL 支持窗口函数,对于查询中的每一行,使用与该行相关的行执行计算。

在您的情况下,您可以使用带有 order by 子句的 RANK() 或 DENSE_RANK() 函数,并在窗口内获取该 MAX(避免慢速连接)。 见:RANK

类似的东西:

select 
    *
from (
SELECT 
    VM.*,
    `VM_Status`.`Status` AS `Status`,
    RANK() OVER(PARTITION BY `VM_Status`.`VmId` ORDER BY `VM_Status`.`InputDate` DESC) rank
    FROM VM left join `VM_Status`
    ON `VM_Status`.`VmId` = `VM`.`VmId`
) `last_status`
WHERE 
    rank = 1

【讨论】:

谢谢,我不知道 RANK()。但是我在 5.7 版上,我的东西 RANK() 仅在 8 上可用。我尝试了一个替代方案,但它从 1 级到 78.000 级返回了 78.000 行......我错过了什么? select * from ( SELECT VM.VmId, VM_Status.Status AS Status, @curRank := @curRank + 1 AS Rank FROM (SELECT @curRank := 0) r, VM 离开加入 VM_Status ON VM_Status.VmId = VM .VmId ORDER BY VM_Status.InputDate DESC ) last_status ORDER BY Rank

以上是关于Mysql left join with nested select慢,如何优化的主要内容,如果未能解决你的问题,请参考以下文章