2016-04-28 7 views
0

Ich habe die folgenden Tabellen:Scalar subquery viel Zeit nehmen, auszuführen

  1. table1 - Sitzungs_ID, company_id, session_start_time
  2. table2 - id, Sitzungs_ID, message_time, message_type, Nachricht
  3. table3 - firmenname, unternehmensname

table1 speichert die Sitzungen von Unternehmen. Jede Sitzung hat viele Nachrichten, die in Tabelle2 gespeichert sind. Für einen bestimmten Nachrichtentyp (z. B. Nachrichtentyp = 2) muss eine Teilzeichenfolge aus der Nachricht extrahiert werden. Dieser Teilstring ist ein Firmenname. Jetzt muss ich die nächste session_id von table1 finden, wobei die company_id mit der des aus der Nachricht extrahierten Firmennamens und der session_start_time> = message_time übereinstimmt.

Ich verwende die folgende Abfrage.

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 

Die ursprüngliche Abfrage ist etwas komplizierter mit ein paar mehr skalaren Unterabfragen. Diese Abfrage dauert außergewöhnlich lange. Ich habe mit der EXPLAIN-Funktion überprüft und die skalare Unterabfrage dauert sehr lange. Ich kann mir keinen besseren Weg vorstellen.

+0

können Sie bitte die EXPLAIN der Abfrage posten –

Antwort

0

Dies ist die Abfrage:

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; 

Zunächst wird die Verwendung von Variablen ist nicht korrekt. MySQL garantiert nicht die Reihenfolge der Auswertung von Variablen in einer SELECT. So müssen Sie in den ursprünglichen Definitionen setzen:

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; 

Als nächstes würde ich versuchen, Indizes: table3(company_name, company_id) und table1(company_id, session_start_time, session_id).