2012-07-26 2 views
3

나는 상기 데이터의 1 년인 12 백만 개의 레지스터를 가진 테이블을 쿼리하는 mysql 작업을하고 있습니다. 쿼리는 특정 종류의 데이터 (코인, 엔터프라이즈, 유형 등)를 선택한 다음 해당 데이터의 특정 필드에 대해 일일 평균을 제공해야하므로 나중에 그래프로 그릴 수 있습니다. 실시간으로이 작업을 수행 할 수 있다는 꿈을 꾸으십시오. 따라서 응답 시간이 10 초 미만이면 순간적으로 볼 때 4 ~ 6 분이 소요됩니다. 예를 들어 where querys가 150k 레지스터를 가지고 하루에 약 500 개를 나눠서 AVG() 및 GroupBy를 사용하여 평균 3 개의 필드 (where 절에 없음)를 평균화합니다.큰 테이블에서의 MySQL 쿼리 최적화

지금, 원시 데이터에 대한 쿼리는 인덱스가 "여기서"레지스터를 사용하지 않고 선택 순서

(fecha, idTipoRA_cache, idMoneda_cache, idEmisorFusionado_cache, plazoResidual) 

에있는 모든 where 절 필드에 걸쳐 만들어

SELECT 
`Valorizacion`.`fecha`, AVG(tir) AS `tir`, AVG(tirBase) AS `tirBase`, AVG(precioPorcentajeValorPar) AS `precioPorcentajeValorPar` 
FROM `Valorizacion` USE INDEX (ix_mercado2) 
WHERE 
(Valorizacion.fecha >= '2011-07-17') AND 
(Valorizacion.fecha <= '2012-07-18') AND 
(Valorizacion.plazoResidual >= 365) AND 
(Valorizacion.plazoResidual <= 3650000) AND 
(Valorizacion.idMoneda_cache IN ('UF')) AND 
(Valorizacion.idEmisorFusionado_cache IN ('ABN AMRO','WATTS', ...)) AND 
(Valorizacion.idTipoRA_cache IN ('BB', 'BE', 'BS', 'BU')) 
GROUP BY `Valorizacion`.`fecha` ORDER BY `Valorizacion`.`fecha` asc; 

248 rows in set (4 min 28.82 sec) 

입니다 그룹 또는 AVG로 그룹

149670 rows in set (58.77 sec) 

그리고 레지스터를 선택하고 그룹화하고 count 평균 소요량은

248 rows in set (35.15 sec) 

입니다. 아마도 인덱스 검색에서 데이터를 검색하기 위해 디스크로 이동해야 할 필요가 없기 때문일 수 있습니다.

내 상사에게 "죄송합니다.하지만 끝낼 수 없습니다"라고 말하면서 최대한 그렇게하기 전에 내가 개선 할 수있는 일이 있다고 생각하는지 묻습니다. . 가장 큰 카디널리티를 가진 인덱스를 앞뒤로 움직이는 인덱스 시간으로 검색을 향상시킬 수 있다고 생각하지만, 그 후에도 각 레코드의 디스크에 액세스하는 데 걸리는 시간과 AVG가 너무 많이 보인다.

아이디어가 있으십니까?

- 편집, 테이블 구조

CREATE TABLE `Valorizacion` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `idInstrumento` int(11) NOT NULL, 
    `fecha` date NOT NULL, 
    `tir` decimal(10,4) DEFAULT NULL, 
    `tirBase` decimal(10,4) DEFAULT NULL, 
    `plazoResidual` double NOT NULL, 
    `duracionMacaulay` double DEFAULT NULL, 
    `duracionModACT365` double DEFAULT NULL, 
    `precioPorcentajeValorPar` decimal(20,15) DEFAULT NULL, 
    `valorPar` decimal(20,15) DEFAULT NULL, 
    `convexidad` decimal(20,15) DEFAULT NULL, 
    `volatilidad` decimal(20,15) DEFAULT NULL, 
    `montoCLP` double DEFAULT NULL, 
    `tirACT365` decimal(10,4) DEFAULT NULL, 
    `tipoVal` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `idEmisorFusionado_cache` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `idMoneda_cache` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `idClasificacionRA_cache` int(11) DEFAULT NULL, 
    `idTipoRA_cache` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `fechaPrepagable_cache` date DEFAULT NULL, 
    `tasaEmision_cache` decimal(10,4) DEFAULT NULL, 
    PRIMARY KEY (`id`,`fecha`), 
    KEY `ix_FechaNemo` (`fecha`,`idInstrumento`) USING BTREE, 
    KEY `ix_mercado_stackover` (`idMoneda_cache`,`idTipoRA_cache`,`idEmisorFusionado_cache`,`plazoResidual`) 
) ENGINE=InnoDB AUTO_INCREMENT=12933194 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 
+0

색인을 추가하는 것이 옵션 인 경우 (잠시 동안 테이블을 잠그는 경우) 'idMoneda_cache, idTipoRA_cache, idEmisorFusionado_cache, plazoResidual' ('plazoResidual' 또는'fecha'가 마지막이어야하는지 확실하지 않음)을 추가하십시오. 그리고'USE INDEX '없이 실행 (또는'EXPLAIN')하십시오. 그 이유는 MySQL은 범위 조건이있는 필드에 대해서만 인덱스를 사용하기 때문입니다 (귀하의 경우 인덱스에서'fecha' 컬럼 만 사용하고있는 경우). – Vatev

+0

그것은 많은 의미가 있습니다. 이제는 1 분 2 초입니다. 행 수 : 193763. 추가 : 사용 위치; 임시 사용; filesort 사용. 그러나 아직 웹 페이지에 올려 놓기에는 너무 느립니다. – Jimmy

+1

여전히 쓸모가 없습니다 ...'SHOW CREATE TABLE ...'(관련이없는 열이 없을 수도 있습니다) 및 전체'EXPLAIN' 출력을 게시 할 수 있습니까 – Vatev

답변

1

12M 기록 중 150K 기록을 선택하고 빠른 상관없이 당신이하려고 무엇을 할 수 없습니다되지 않습니다 그들에 집계 기능을 수행.

샘플 검색어가 1 년간의 데이터이므로 주로 역사적인 데이터를 다루는 것입니다. 더 나은 방법은 일일 평균을 미리 계산하여 별도의 테이블에 넣는 것입니다. 그런 다음보고, 그래프 등을 위해 이러한 테이블을 쿼리 할 수 ​​있습니다. 동일한 데이터에서 다시 계산할 필요가 없도록 이러한 계산을 실행할시기와 방법을 결정해야합니다.

수백만 개의 기록 레코드에 대한 분석 및보고를 수행해야하는 경우 간단한 데이터베이스 방식이 아닌 데이터웨어 하우스 접근 방식 http://en.wikipedia.org/wiki/Data_warehouse을 고려해야합니다.

+0

당신은 완전히 정확합니다, 감사합니다 :) – Jimmy