2012-05-24 2 views
0

내 쿼리를 더 빠르게 만드는 방법에 대해 제발 나를 설명하거나 설명해 줄 수 있습니까? 이 쿼리는 거의 1GB 데이터를 사용하여 (로컬 컴퓨터에서) 거의 10 초 걸립니다. 여기내 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
가능 YS : IDX1
키 IDX1
있는 key_len 4
REF : CONST 행
: 40,258
추가 : 사용

ID : 1 개
선택 유형 : 간단한 테이블
: S
유형 : REF
가능한 키 : 키 IDX1
: IDX1
있는 key_len 63
,745,151 5,REF : CONST, APC_DB.p.delivery_hour, APC_DB.p.participant_id, APC_DB.p.resource_id, CONST 행
: 추가 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이 p의 모든 행에 닿을 때마다 s의 모든 행에 대해 hour(s.date_posted)date(s.date_posted)을 계산하도록합니다.

이 시도 보내기

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 : 계산 된 부분의 반복 BETWEEN의 최대 한도는 purpouse입니다 : MySQL은 한 번만 계산할 것입니다.

편집 3 : 지금 보는 당신의 SHOW CREATE TABLE, 난 당신이 date_posted에 별도의 인덱스,하지만 단지 결합 인덱스가없는 이해합니다.시도해 볼 수도 있습니다

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

. 쿼리 속도가 거의 1 초 단축되었습니다. 더 많은 인덱스를 추가해야한다고 생각합니까? 고맙습니다. – leka

+0

릭 - 내 로컬 및 내 서버에서 20 초 (내 인터넷 연결 일 수 있음) 2.96 초에 속도를 줄여 주셔서 감사합니다. – leka

관련 문제