2012-09-26 74 views
2

在表'ttraces'中,我有許多不同任務的記錄(它們的值保存在'taskid'列中,並且是列的外鍵'id'在表'ttasks'中)。每個任務每8-10秒插入一個記錄,以緩存數據以提高性能並不是一個好主意。我需要的是僅從'ttraces'中爲每個任務選擇最新的記錄,這意味着具有列'time'最大值的記錄。目前,我在桌上有超過50萬條記錄。這兩個表的非常簡單的結構如下所示:MySQL:如何提高選擇查詢的速度,包含2個連接和1個子查詢

----------------------- 
|  ttasks  | 
----------------------- 
| id | name | blocked | 
----------------------- 

--------------------- 
|  ttraces  | 
--------------------- 
| id | taskid | time | 
--------------------- 

我的查詢如下所示:

SELECT t.name,tr.time 
FROM 
    ttraces tr 
    JOIN 
    ttasks t ON tr.itask = t.id 
    JOIN (
     SELECT taskid, MAX(time) AS max_time 
     FROM ttraces 
     GROUP BY itask 
    ) x ON tr.taskid = x.taskid AND tr.time = x.max_time 
WHERE t.blocked 

在所使用的所有列和JOIN子句的索引。至於查詢運行時間約爲1.5秒。提高速度至關重要。感謝您的所有建議。 BTW:數據庫運行在託管的共享服務器上,暫時我無法在其他地方移動它。

[編輯] EXPLAIN SELECT ...結果是:

-------------------------------------------------------------------------------------------------------------- 
id select_type table  type  possible_keys key  key_len ref   rows  Extra 
-------------------------------------------------------------------------------------------------------------- 
1 PRIMARY  <derived2> ALL  NULL   NULL  NULL  NULL   74 
1 PRIMARY  t   eq_ref PRIMARY   PRIMARY 4   x.taskid  1  Using where 
1 PRIMARY  tr   ref  taskid,time  time  9   x.max_time 1  Using where 
2 DERIVED  ttraces  index NULL   itask  5   NULL   570853 
-------------------------------------------------------------------------------------------------------------- 

發動機是InnoDB的。謝謝。

+3

'EXPLAIN'說什麼? – wroniasty

+0

「在WHERE和JOIN子句中使用的所有列都被索引」 - >爲什麼你有一個被阻塞的索引?這是沒用的 – Cosmin

+0

沒有'EXPLAIN'輸出,你沒有說什麼存儲引擎被使用,什麼MySQL設置等等。在共享服務器上運行數據庫是一個可怕的想法,你不能保證服務器將足夠的資源您的目的和數據庫匱乏,需要更多來自HDD子系統的IOPS。 –

回答

0

如果每個任務的痕跡很多,那麼您可以只保留一張只有最新痕跡的表格。當你插入ttraces也UPSERT到ttraces_newest:

insert into ttraces_newest (id, taskid, time) values 
(3, 1, '2012-01-01 08:02:01') 
on duplicate key update 
`time` = current_timestamp 

到ttraces_newest的主鍵是(ID,任務id)。查詢ttraces_newest會更便宜。便宜多少取決於每個任務有多少軌跡。現在查詢是:

SELECT t.name,tr.time 
FROM 
    ttraces_newest tr 
    JOIN 
    ttasks t ON tr.itask = t.id 
WHERE t.blocked 
+0

是的,我已經考慮過了,如果我只想檢索最新的數據,這顯然有幫助。但是,我還需要有機會選擇一些檔案記錄(適合某個時間段,即不比'2012-09-20 10:00:00'更新),問題依然存在。無論如何,謝謝你的建議。 – peterp

0

這裏是我的想法......你需要在具有taskidtime列(按順序)ttraces一個綜合指數。比,使用此查詢:

SELECT t.name, 
     trm.mtime 
FROM ttasks AS t 
     JOIN (SELECT taskid, 
        Max(time) AS mtime 
      FROM ttraces 
      GROUP BY taskid) AS trm 
     ON t.id = trm.taskid 
WHERE t.blocked 
0

此代碼是否返回正確的結果呢?如果是這樣,它的速度時間如何?

SELECT t.name, max_time 
FROM ttasks t JOIN ( 
    SELECT taskid, MAX(time) AS max_time 
    FROM ttraces 
    GROUP BY taskid 
) x ON t.id = x.taskid 
1

我可能會有一點時刻,但是這個查詢不是邏輯上相同,(幾乎肯定)更快?

SELECT t.id, t.name,max(tr.time) 
FROM 
ttraces tr 
JOIN 
ttasks t ON tr.itask = t.id 
where BLOCKED 
group by t.id, t.name 
+0

這也是我的想法 – RomanKonz

+0

是的,你似乎是正確的:)響應時間縮短了兩次。謝謝。 – peterp