2016-03-02 99 views
2

我目前嘗試優化MySQL語句。它需要約10秒,並輸出兩個整數的平均差。事件表包含6個列,並由它的id和run_id +每隔一個鍵索引。MySQL:優化加入

該表總共保存了run_id 37,4162050的3308000行。 大部分時間似乎都需要加入,所以也許有一種方法來加速它。

send.element_id和recv.element_id是唯一的,有沒有辦法在sql中表達它可能導致更好的性能?

|------------------- 
|Spalte  Typ 
|------------------- 
|run_id  int(11) 
|element_id int(11) 
|event_id int(11)  PRIMARY 
|event_time int(11) 
|event_type varchar(20) 
|event_data varchar(20) 

查詢:

select avg(recv.event_time-send.event_time) 
from 
(
select element_id, event_time 
from event 
where run_id = 37 and event_type='SEND_FLIT' 
) send, 
(
select element_id, event_time 
from event 
where run_id = 37 and event_type='RECV_FLIT' 
) recv 
where recv.element_id = send.element_id 

查詢的解釋:

+----+-------------+------------+------+-----------------------------------------------------+-------------+---------+-------------+--------+-----------------------+ 
| id | select_type | table  | type | possible_keys          | key   | key_len | ref   | rows | extra     | 
+----+-------------+------------+------+-----------------------------------------------------+-------------+---------+-------------+--------+-----------------------+ 
| 1 | PRIMARY  | <derived3> | ALL | NULL            | NULL  | NULL | NULL  | 499458 | NULL     | 
| 1 | PRIMARY  | <derived2> | ref | <auto_key0>           | <auto_key0> | 4  | element_id | 10  | NULL     | 
| 3 | DERIVED  | event  | ref | run_id,run_id_2,run_id_3,run_id_4,run_id_5,run_id_6 | run_id_5 | 26  | const,const | 499458 | Using index condition | 
| 2 | DERIVED  | event  | ref | run_id,run_id_2,run_id_3,run_id_4,run_id_5,run_id_6 | run_id_5 | 26  | const,const | 562556 | Using index condition | 
+----+-------------+------------+------+-----------------------------------------------------+-------------+---------+-------------+--------+-----------------------+ 
+0

如果「send.element_id和recv.element_id是獨一無二的」,那麼,「加入」「recv.element_id = send.element_id」意味着你在同一行?沒有? –

+0

我的意思是每個element_id只有一個'SEND_FLIT'事件,因此該列是唯一的。同樣適用於'RECV_FLIT'。所以我不在同一行,但它只存在一個可以連接的其他行。 – user1238052

回答

3

一種方式是按element_id和使用sum確定的差別,你可以再傳遞給avg

select avg(diff) from (
    select 
     sum(case when event_type = 'SEND_FLIT' then -1 * event_time else event_time end) 
     as diff 
    from event 
    where run_id = 37 
    and event_type in ('SEND_FLIT','RECV_FLIT') 
    group by element_id 
) t 
+0

我真的很喜歡這種方式,但表現明智,它在同一聯盟(只是測試它,略高於10秒)。該組通過搜索element_id的所有值並且如果找到2(我的猜測)不會停止。我不知道是否有可能在sql語句中使用有關數據記錄的知識。 – user1238052

+0

這個查詢假設每個'element_id'只有1個'RECV_FLIT'和'SEND_FLIT',這意味着每個組將有2個元素。 '(run_id,event_type,element_id)'上的複合索引可能會有所幫助。 – FuzzyTree

+0

額外的索引似乎有點幫助,猜測我對這個組錯了,忘記了索引了。查詢似乎儘可能的好,所以我會與剩下的8秒生活在一起。 – user1238052