2010-10-22 90 views
4

我有一個表,其中存儲pupil_id,類別和生效日期(除其他事項外)。日期可以是過去,現在或未來。我需要一個查詢來從表格中提取學生的當前狀態。我怎樣才能優化這個MySQL查詢?

以下查詢的工作原理:

SELECT * 
FROM pupil_status 
WHERE (status_pupil_id, status_date) IN (
    SELECT status_pupil_id, MAX(status_date) 
    FROM pupil_status 
    WHERE status_date < NOW() -- to ensure we ignore the "future status" 
    GROUP BY status_pupil_id); 

在MySQL,該表被定義如下:

CREATE TABLE IF NOT EXISTS `pupil_status` (
    `status_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `status_pupil_id` int(10) unsigned NOT NULL, -- a foreign key 
    `status_category_id` int(10) unsigned NOT NULL, -- a foreign key 
    `status_date` datetime NOT NULL, -- effective date/time of status change 
    `status_modify` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `status_staff_id` int(10) unsigned NOT NULL, -- a foreign key 
    `status_notes` text NOT NULL, -- notes detailing the reason for status change 
    PRIMARY KEY (`status_id`), 
    KEY `status_pupil_id` (`status_pupil_id`,`status_category_id`), 
    KEY `status_pupil_id_2` (`status_pupil_id`,`status_date`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1409 ; 

然而,隨着950級的學生和剛剛超過1400點的狀態在表中,查詢採用0.185秒來處理。現在也許可以接受,但是當桌子膨脹時,我擔心可擴展性。生產系統可能會有超過10000名學生,每個學生都有15-20個狀態。

有沒有更好的方法來寫這個查詢?是否有更好的索引來幫助查詢?請告訴我。

回答

4

有以下幾件事你可以嘗試

1使用INNER JOIN代替WHERE

SELECT * 
FROM pupil_status ps 
INNER JOIN 
    (SELECT status_pupil_id, MAX(status_date) 
    FROM pupil_status 
    WHERE status_date < NOW() 
    GROUP BY status_pupil_id) X 
ON ps.status_pupil_id = x.status_pupil_id 
AND ps.status_date = x.status_date 

2具有可變和存儲的值NOW() - 我不知道數據庫引擎將NOW()的呼叫優化爲只有一個呼叫,但是如果不呼叫,則可能會有所幫助

這些是一些建議,但您需要比較查詢計劃並查看是否有任何可觀的改進或不。 根據您對查詢計劃的索引使用情況,上面的robob的建議也可以派上用場

+0

謝謝!我沒有意識到在WHERE ... IN和INNER JOIN之間會有這麼令人難以置信的區別。與10000000名學生的200000個狀態,查詢返回0.08秒比上述查詢超過5分鐘(然後我厭倦了等待)的查詢。儘管我沒有改變鑰匙,但不確定它的必要性。 – Philip 2010-10-22 06:16:23

1

查看當您使用每個具有15-20個狀態的10000個學生加載系統時查詢需要多長時間。

只有在需要太長時間的情況下才會重構。

+0

看起來太明智了;-)我會快速生成一些隨機數據,看看會發生什麼...... – Philip 2010-10-22 05:55:34

+0

長,長時間... – Philip 2010-10-22 06:16:57

+0

連接,索引和內存緩存是你的朋友然後... – jeffo 2010-10-22 07:06:48