2012-05-10 2 views
1

두 개의 MySQL 테이블을 결합하여 뷰로 저장하고자하므로 두 테이블을 쿼리하는 대신 응용 프로그램에서이 뷰를 처리 할 수 ​​있습니다. 그러나이 견해는 극도로 천천히 진행됩니다.MySQL보기 최적화

이 내 테이블입니다 :

CREATE TABLE spectrumsets (
    setid INT(11) NOT NULL, 
    timestampdt INT(11) NULL DEFAULT NULL, 
    timestampd INT(10) UNSIGNED NOT NULL, 
    timestampt INT(10) UNSIGNED NOT NULL, 
    device INT(11) NOT NULL, 
    methodname VARCHAR(50) NOT NULL, 
    PRIMARY KEY (setid), 
    UNIQUE INDEX setid_idx (setid), 
    UNIQUE INDEX timestamp_device_idx (timestampd, timestampt, device), 
    INDEX device_fk (device), 
    INDEX timestampd_idx (timestampd), 
    CONSTRAINT device_fk FOREIGN KEY (device) 
     REFERENCES spectrumdevices (deviceid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

CREATE TABLE spectrumdata (
    valueid INT(11) NOT NULL AUTO_INCREMENT, 
    spectrumset INT(11) NOT NULL, 
    wavelength DOUBLE NULL DEFAULT NULL, 
    intensity DOUBLE NULL DEFAULT NULL, 
    PRIMARY KEY (valueid), 
    INDEX spectrumset_idx (spectrumset), 
    CONSTRAINT spectrumset_fk FOREIGN KEY (spectrumset) 
     REFERENCES spectrumsets (setid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

그리고 이것은 내보기입니다 :

SELECT spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength,spectrumdata.intensity 
FROM spectrumdata INNER JOIN spectrumsets ON spectrumdata.spectrumset= 
    spectrumsets.setid 
WHERE spectrumdata.wavelength>0 
ORDER BY spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength 

내 컴퓨터에 select count(*) 그래서, 82923705 개 기록에 오히려 큰 데이터 세트를 385.516 초 결과를 소요

나는 이미이 link을 발견했지만 아직도 잘못 이해하지는 못했습니다.

UPDATE :

EXPLAIN주는이 결과 :

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra" 
"1","SIMPLE","spectrumsets","index","PRIMARY,setid_idx","timestamp_device_idx","12",NULL,"327177","Using index; Using temporary; Using filesort" 
"1","SIMPLE","spectrumdata","ref","spectrumset_idx","spectrumset_idx","4","primprod.spectrumsets.setid","130","Using where" 
+2

당신은 EXPLAIN 사용했다? –

+0

'analyze tables spectrumdata spectrumsets '을 실행하면 어떤 차이가 있습니까? – Bohemian

+1

buffer_pool_size는 무엇입니까? 데이터 세트가 메모리에 들어 가지 않는 것처럼 보입니다. 그래서 전체 테이블 스캔을하는 동안 InnoDB가 디스크를 강탈하고있는 것 같습니다. –

답변

2

이 설명은 쿼리가 (좋은) 조인에 대한 인덱스를 타격,하지만 임시 테이블 및 파일 종류에 대한을 사용하고 있음을 시사한다 나머지 쿼리.

이 두 가지 이유가 있습니다 :

  • where 절은 인덱스
  • ORDER BY 절을 타격하지 않는 코멘트에서 인덱스

타격하지 않습니다, 당신은 말한다 where 절을 제거하면 커다란 개선으로 이어진다. 스펙트럼 세트, 파장에 복합 지수가 필요하다는 것을 의미합니다. 파장이 적절한 값을 가질 수 있다고 가정합니다 (단 10 개의 값이라면 인덱스는 아무 것도 할 수 없습니다).

"order by"절을보기 밖으로 벗어나면 훨씬 빠르게 처리됩니다. 그리고 정렬 순서를보기가 아닌 쿼리 추출 데이터로 결정할 수있는 좋은 경우가 있습니다. 나는 대부분의 쿼리가 데이터에 대해 매우 선택적 일 것이라고 추측한다. 몇 개의 타임 스탬프로 제한한다. 보기에 순서를 포함시킴으로써 매번 정렬 할 때 가격을 지불하게됩니다.

보기에서 "order by"가 있어야하는 경우 "order by"순서로 모든 필드를 포함하는 색인을 만들고 앞에있는 조인을 사용하십시오. 예를 들어 :

UNIQUE INDEX의 timestamp_device_idx (set_id, timestampd, timestampt, 장치),

+0

+1. 이것은 정답이지만 MySQL 5입니다.0+는 [index merge] (http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html)를 사용하여 둘 이상의 색인을 사용할 수 있습니다. 저는 그 진술을 반대로 삭제하거나 명확히 할 것입니다. 또한, 인덱스에 대한 범위를 사용하면 나머지 부분이 무효화되기 때문에 범위를 사용하는 열 (이 경우에는 파장 열, 'WHERE wavelength> 0'참조)을 사용하는 열을 입력하십시오. 그 외의 경우 우선 카디널리티가 가장 높은 열을 배치하십시오. –

+0

몇 가지 테스트를 수행 했습니까? ORDER BY 절을 제거하면 약 385 초에서 약 285 초 사이의 성능 시간이 줄어들지 만 WHERE 절도 약 48 초 사이에서 제거됩니다! 그래서 나는 ORDER BY 절을 호출 응용 프로그램으로 옮기고 WHERE 절을 옮겨야한다고 생각합니다. 필자의 경우에는 문제가 아니지만, 아직 어떤 일이 벌어지고 있는지 완전히 이해하지 못하고있다 :-(innodb_buffer_pool_size를 가지고 뭔가를 가질 것이지만, 뷰의 SQL 문을 구성 할 수도있다.) – waanders

+0

그건 정말 좋은 지적이다. 그 문제를 일으키는 절, 그에 따라 대답을 편집 할 것입니다. –