2013-05-07 140 views
0

我有兩個表在同一個數據庫DeviceEventData;兩個表都有accountIDdeviceID列,這些列也是主鍵。MySQL查詢與子查詢慢

Device表中有一列名爲linkDescription的列。

我需要複製一些行,表EventData,其accountIDdeviceID,在Device表,具有linkDescription列一些文本。

例子:

器表

accountID DeviceID linkDescription 
12345  5800  444 
12345  5700  445 
12345  5500  null <--literally null 
12388  4400  555 
12388  4450  555 

EVENTDATA表

accountID DeviceID timestamp 
12345  5800  123335544 
12345  5700  123335544 
12345  5500  123335544 
12388  4400  123335544 
12388  4450  123335544 
12345  5800  123335548 
12345  5700  123335549 
12345  5500  123335549 
12388  4400  123335545 
12388  4450  123335546 

現在我需要使用linkDescription從重複上EventData一些行,改變表;所以EventData現在有以下數據:

accountID DeviceID timestamp 
12345  5800  123335544 
12345  5700  123335544 
12345  5500  123335544 
12388  4400  123335544 
12388  4450  123335544 
12345  5800  123335548 
12345  5700  123335549 
12345  5500  123335549 
12388  4400  123335545 
12388  4450  123335546 
444   5800  123335544 <-duplicated data with new accountID from here 
445   5700  123335544 
555   4400  123335544 
555   4450  123335544 
444   5800  123335548 
445   5700  123335549 
555   4400  123335545 
555   4450  123335546 

所以現在我測試下面的查詢這將是INSERT INTO中更大的一部分:

explain 
select * 
from EventData 
where 
    EventData.accountID in (
     select accountID 
     from Device 
     where Device.linkDescription > '0') 
    and EventData.deviceID in (
     select deviceID 
     from Device 
     where Device.linkDescription> '0') 
    and timestamp > (unix_timestamp(now()-interval 20 minute)); 

不過是二慢,EXPLAIN命令顯示此:

ID select_type   table  type   posible_keys key key_len ref  rows  Extra 
1 PRIMARY    EventData ALL    null   null null null 47555718 Using where 
3 DEPENDENT SUBQUERY Device  ALL    null   null null null 8043  Using where 
2 DEPENDENT SUBQUERY Device  index_subquery PRIMARY  PRIMARY 34 func  3  Using where 

所以,據我瞭解,至少,是檢查整個表,這就是爲什麼如此緩慢。

我該怎麼做我想要的更快?

+4

嘗試使用'JOIN's。 – Kermit 2013-05-07 18:25:17

+0

'in'條件可以很好地處理確定性集合(例如:in(1,2,3,5)',但對於子查詢它們可能是災難性的,因爲子查詢需要爲每一行計算一次。做到這一點 – Barranka 2013-05-07 19:40:33

+0

我有一個寫在EventData表上的JAVA模塊,所以我想我會重新編寫代碼來做我想做的事情。我有一個VB.NET程序並且按照你說的做類似的事情查詢分開,並創建一個新的查詢,所有內部的IN;因此不需要子查詢 – 2013-05-07 20:27:04

回答

0

我不確定你的問題是你想做什麼,但你應該使用JOIN來加快速度。你SELECT可以寫更多像這樣的:

SELECT EventData.accountID from 
EventData 
RIGHT JOIN Device 
ON 
(
    (
     Device.accountID = EventData.accountID 
     OR Device.deviceID = Event.deviceID 
    ) 
    AND Device.linkDescription> '0' 
    AND timestamp > (unix_timestamp(now()-interval 20 minute)) 
); 

你或許可以制定出INSERT如何從那裏工作。

+0

我改變了一個AND的OR,並返回了很多或一個列中的空值 – 2013-05-07 20:28:20

+0

嗯,你能簡化它看看有什麼不對嗎? – woz 2013-05-07 20:30:04

0

考慮使用JOIN的,而不是where條件:

select ed.* 
from 
    EventData as ed 
    inner join Device as d1 on ed.accountId = d1.accountId 
    inner join Device as d2 on ed.deviceId = d2.deviceId 
where 
    d1.linkDescription > '0' 
    and d2.linkDescription > '0' 
    and ed.timestamp > (unix_timestamp(now()-interval 20 minute)); 

我複製Device表來糾正你的查詢。如果這兩個條件必須同時滿足,則只需使用Device表一次:

select ed.* 
from 
    EventData as ed 
    inner join Device as d on ed.accountId = d.accountId and ed.deviceId = d.deviceId 
where 
    d.linkDescription > '0' 
    and d.linkDescription > '0' 
    and ed.timestamp > (unix_timestamp(now()-interval 20 minute)); 

希望這有助於

+0

通常需要多少時間才能像MySQL表上的查詢那樣有4700萬行?因爲我在程序中使用的大多數查詢不會超過幾個秒ybe我期待從數據庫引擎太多。 – 2013-05-07 18:58:44

+0

@E_Blue事實上,你的表格很大,但是你需要考慮在你的表格中每行都會評估一次「in(select ...)」條件**,所以這對性能是一個懲罰。這就是爲什麼我建議使用連接。如果你的表有適當的索引,那應該會加快速度 – Barranka 2013-05-07 19:37:43

0

它不一定是你的子查詢是緩慢的,它的主要表爲47萬行:

和時間戳>(unix_timestamp(now() - interval 20 minute));

在時間戳上添加索引。這應該解決它。我將指出,在現代版本的mysql中,子查詢和連接在性能上沒有實際差別。然而,連接更清晰並且更易於理解。

+0

我已經試過了,沒有時間戳,EXPLAIN命令返回相同的結果。 – 2013-05-07 19:00:07