2012-05-24 91 views
0

有人可以幫我請或向我解釋如何使我的查詢更快?這個查詢幾乎需要10秒(在本地機器上),幾乎有1GB的數據。需要幫助,使我的MySQL查詢更快

這是我的解釋和說明resuls

explain select p.delivery_date, p.delivery_hour, p.resource_id, p.participant_id, p.price, p.date_posted, hour(p.date_posted) as hour_date_posted, date(p.date_posted) as date_date_posted 
    ,s.mw 
from prices_report as p 
left join schedules_report s 
on s.delivery_date = p.delivery_date 
        AND s.type_id = p.type_id 
      and s.delivery_hour = p.delivery_hour 
        and s.resource_id = p.resource_id 
        and s.participant_id = p.participant_id 
        and hour(s.date_posted) = hour(p.date_posted) 
        and date(s.date_posted) = date(p.date_posted) 
WHERE p.delivery_date = '2012-05-22' 
AND p.type_id = 'GEN' 
ORDER BY p.delivery_date, p.resource_id, p.delivery_hour, p.participant_id, p.type_id, p.date_posted 

enter image description here

解釋結果:
ID:1種
選擇類型:簡單
表:P
類型: ref
可能ke YS:IDX1
鍵:IDX1
key_len:4
REF:常量
行:40258
額外:使用其中

ID:1種
選擇類型:簡單
表:■
類型:參考
可能的鍵:idx1
鍵:idx1
key_len:63
REF:常量,APC_DB.p.delivery_hour,APC_DB.p.participant_id,APC_DB.p.resource_id,常量
行:99
額外:

表結構:

CREATE TABLE `prices_report` (
    `id` int(11) NOT NULL auto_increment, 
    `delivery_date` date default NULL, 
    `delivery_hour` int(2) default NULL, 
    `participant_id` varchar(10) default NULL, 
    `resource_id` varchar(15) default NULL, 
    `type_id` varchar(10) default NULL, 
    `price` float default NULL, 
    `date_posted` datetime NOT NULL, 
    `date_created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `IDX1` USING BTREE (`delivery_date`,`resource_id`,`delivery_hour`,`participant_id`,`type_id`,`date_posted`) 
) ENGINE=MyISAM AUTO_INCREMENT=5261441 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC; 


CREATE TABLE `schedules_report` (
    `id` int(11) NOT NULL auto_increment, 
    `delivery_date` date default NULL, 
    `delivery_hour` int(2) default NULL, 
    `participant_id` varchar(15) default NULL, 
    `resource_id` varchar(20) default NULL, 
    `type_id` varchar(10) default NULL, 
    `mw` float default NULL, 
    `loss_factor` float default NULL, 
    `date_posted` datetime NOT NULL, 
    `date_created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `IDX1` USING BTREE (`delivery_date`,`delivery_hour`,`participant_id`,`resource_id`,`type_id`,`date_posted`) 
) ENGINE=MyISAM AUTO_INCREMENT=43369 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC; 

萬元感謝

+0

prices_report和schedules_report中有多少行?該日期有多少記錄?請同時顯示架構/索引。 – Ami

回答

2

這個問題似乎是 「模糊匹配」:

LEFT JOIN ... ON ... 
and hour(s.date_posted) = hour(p.date_posted) 
and date(s.date_posted) = date(p.date_posted) 

強制MySQL爲s中的所有行計算hour(s.date_posted)date(s.date_posted),每次觸及p中的一行時。

這給一試:

and s.date_posted 
    BETWEEN DATE_SUB(p.date_posted, INTERVAL TIME_TO_SEC(MAKETIME(0,MINUTE(p.date_posted),SECOND(p.date_posted))) SECOND) 
    AND DATE_ADD(DATE_SUB(p.date_posted, INTERVAL TIME_TO_SEC(MAKETIME(0,MINUTE(p.date_posted),SECOND(p.date_posted))) SECOND), INTERVAL 1 HOUR) 

編輯:

如果你能閏秒的生活被錯誤地計算,這可以寫成一個更可讀

and s.date_posted 
    BETWEEN DATE_SUB(p.date_posted, INTERVAL 60*MINUTE(p.date_posted)+SECOND(p.date_posted) SECOND) 
    AND DATE_ADD(DATE_SUB(p.date_posted, INTERVAL 60*MINUTE(p.date_posted)+SECOND(p.date_posted) SECOND), INTERVAL 1 HOUR) 

編輯2: 重複部分計算的VA在的上限中,lue在purpouse上:MySQL將只計算一次。

編輯3: 現在看到你SHOW CREATE TABLE,我知道你沒有對date_posted一個單獨的索引,而只是一個組合索引。您可能想嘗試

ALTER TABLE `schedules_report` ADD INDEX(date_posted) 
+0

謝謝。查詢速度降低了近一秒。你認爲我應該增加更多的索引嗎?非常感謝你 – leka

+0

瑞克 - 非常感謝你在本地減少了2.96秒的速度,並在我們的服務器上減少了20秒(可能是我的互聯網連接) – leka