标量子查询需要花费大量时间来执行

时间:2016-04-28 11:19:31

标签: mysql sql scalar-subquery

我有以下表格:

  1. table1 - session_id,company_id,session_start_time
  2. table2 - id,session_id,message_time,message_type,message
  3. table3 - company_id,company_name
  4. table1存储在公司上完成的会话。每个会话都有很多消息,这些消息存储在table2中。对于特定的message_type(比如message_type = 2),需要从消息中提取子字符串。该子字符串是公司名称。现在我需要从table1中找到下一个session_id,其中company_id与从message中提取的公司名称的session_id匹配,session_start_time> = message_time。

    我正在使用以下查询。

    select t1.session_id as session1,
           t1.company_id as company1,
           @transfer_time := t2.message_time as transfer_time,
           @company2 := trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) as company2,
           (select t1.session_id
            from table1 as t1
              inner join table3 as t3 on t1.company_id = t3.company_id
            where t1.session_start_time >= @transfer_time
              and t3.company_name = @company2
           order by t1.session_start_time
           limit 1) as session 2
    from table1 as t1
      inner join table2 as t2 on t1.session_id = t2.session_id
      inner join table3 as t3 on t1.company_id = t3.company_id
    where t2.message_type = 2
    

    原始查询稍微复杂一点,有一些标量子查询。此查询执行时间过长。我检查了explain函数,标量子查询似乎需要很长时间才能执行。但是,我无法想到更好的方法。

1 个答案:

答案 0 :(得分:0)

这是查询:

select t1.session_id as session1, t1.company_id as company1,
       @transfer_time := t2.message_time as transfer_time,
       @company2 := trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) as company2,
       (select t1.session_id
        from table1 t1 inner join
             table3 t3
             on t1.company_id = t3.company_id
        where t1.session_start_time >= @transfer_time and
              t3.company_name = @company2
        order by t1.session_start_time
        limit 1
       ) s session 2
from table1 t1 inner join
     table2 t2
     on t1.session_id = t2.session_id inner join
     table3 t3
     on t1.company_id = t3.company_id
where t2.message_type = 2;

首先,使用变量是不正确的。 MySQL不保证SELECT中变量的评估顺序。所以,你需要输入原始定义:

select t1.session_id as session1, t1.company_id as company1,
       t2.message_time as transfer_time,
       trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) as company2,
       (select t1.session_id
        from table1 t1 inner join
             table3 t3
             on t1.company_id = t3.company_id
        where t1.session_start_time >= t2.message_time and
              t3.company_name = trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) 
        order by t1.session_start_time
        limit 1
       ) s session 2
from table1 t1 inner join
     table2 t2
     on t1.session_id = t2.session_id inner join
     table3 t3
     on t1.company_id = t3.company_id
where t2.message_type = 2;

接下来,我会尝试索引:table3(company_name, company_id)table1(company_id, session_start_time, session_id)