SQL 内部联接 - 性能改进

SQL inner join - performance improvement

我有以下 SQL 但希望提高性能(下面的选项 2 目前大约需要 24 秒)。

EXPLAIN MySQL - 在下面的答案中使用示例

选项 1 - 基本 select(非常慢)

select f.name, f.flowid, m.traceid, m.traceday, m.logtimestamp
from flow f, messageinfo m 
where traceid = (select max(traceid) from messageinfo where flowid = f.flowid)

更新

选项 2 - 使用内部连接(更快但仍然太慢)

select m.traceid, f.name, f.flowid, m.traceday, m.logtimestamp
from flow f
  inner join messageinfo m 
  on m.flowid = f.flowid
  where traceid = (select max(traceid) from messageinfo where flowid = 
  f.flowid)
order by f.name

我需要遍历流记录(大约有 900 个),对于每个流 select 消息信息中的相关流 table 是最新的,即具有最高的 traceid对于那个特定的流程。上面的两个 SQL 示例都有效,但我想看看我是否可以在可能的情况下提高选项 2 的性能。最终结果应该是尽力而为,只有 return 一个可以找到相关流记录的 traceid(如内部连接)。 谁能建议一种更高效的方法?请记住,我想在最终结果中 return 来自两个 table 的数据(如上例所示)。

我还需要强调,我没有修改带有 new/updated 索引的数据库的自由。所以主要是在不修改数据库的情况下寻找 SQL 的改进。

也就是说,注意到任何索引改进对于未来的工作仍然是有益的。

您可以使用 SQL 索引来快速检索您的数据。你看不到索引,它们只是用来加速 searches/queries。以下是添加索引的语法。

CREATE INDEX index_name
ON table_name (column1, column2, ...);

另一种使用连接重写查询的方法,将依赖的子查询部分移至子句并将其与主查询连接。

select m.traceid, f.name, f.flowid, m.traceday, m.logtimestamp
from flow f
inner join messageinfo m on m.flowid = f.flowid
inner join (
    select flowid, max(traceid) traceid
    from messageinfo 
    group by flowid
) m1 on  m.flowid = m1.flowid and m.traceid = m1.traceid
order by f.name

同时在 (flowid,traceid) 上添加复合索引

以及所有相关表的 SHOW CREATE TABLE 语句,有关查询性能的问题始终是给定查询的 EXPLAIN。

就是说,在等待必要信息出现的同时,根据我的经验,不相关的子查询有时会胜过相关的子查询,所以我很想尝试以这种方式编写查询:

select m.traceid
     , f.name
     , f.flowid
     , m.traceday
     , m.logtimestamp
  from flow f
  join messageinfo m 
    on m.flowid = f.flowid
  Join
     ( select flowid
            , max(traceid) traceid 
         from messageinfo 
        Group
           By flowid
     ) x
    On x.flowid = f.flowid
   And x.traceid = m.traceid
 order 
    by f.name

您的查询很好——尽管您应该使用限定的列名编写它所有列:

select m.traceid, f.name, f.flowid, m.traceday, m.logtimestamp
from flow f inner join
     messageinfo m 
     on m.flowid = f.flowid
where m.traceid = (select max(m2.traceid) from messageinfo m2 where m2.flowid = m.flowid)
order by f.name;

您需要 messageinfo(flowid, traceid) 上的索引。 flow(name, flowid) 上的索引也可能有帮助。

为什么不使用像这样的 window 函数: max(traceid) over(partition by traceid order by traceid) 来自消息信息

?