2017-05-22 5 views
0

이 쿼리를 어떻게 최적화 된 상태로 빠르게 수행 할 수 있는지 묻고 싶습니다. 어쨌든 그것은 많은 행에 대해 매우 느리게 작동합니다. 같은 세 테이블에 대한 인덱스는 여전히 매우 큰 테이블을 통한 빠른 검색을 허용하지 않습니다. 제발, 어떤 충고와 개선에 대해 매우 감사드립니다. 고맙습니다.큰 테이블에 대한 결과 쿼리가 매우 느림 (왼쪽에 두 개의 테이블이 결합 된 경우)

SET @timeset := 0; 
SET @timeset2 := 0; 
SET @previousDay := 0; 
SET @previousDay2 := 0; 
SET @datefrom = cast('2017-05-01 00:00:00' as datetime); 
SET @dateto = cast('2017-05-15 00:00:00' as datetime); 

SET @rownumFirstTable := 0; 
SET @rownumSecondTable = 0; 

SELECT 

    `hour_time_local`, 
    DAY(`hour_time_local`) AS `day`, 
    IF(DAY(`hour_time_local`) != @previousDay, @timeset:=0, @timeset:=1) AS ``, 
    @rownumFirstTable := IF(@timeset != 0, @rownumFirstTable :[email protected] +1, @rownumFirstTable :=1) AS `row_first_table`, 
    @previousDay := DAY(`hour_time_local`), 

    `low_speed` AS `LOW_SPEED_15_PERCENTILE`, 
    `day_second_table`, 
    `LOW_SPEED_15_PERCENTILE_INDEX`, 

    `row_second_table`, 
    `high_speed`, 
    `hour_time_second_table`, 
    `day_second_table`, 
    `HIGH_SPEED_15_PERCENTILE_INDEX` 

FROM 
    t.table_speed AS `first_table` 

LEFT JOIN 
(
    SELECT 
     COUNT(low_speed) AS `count_low_speed`, 
     CEIL((15/100) * COUNT(low_speed)) AS `LOW_SPEED_15_PERCENTILE_INDEX`, 
     CEIL((15/100) * COUNT(high_speed)) AS `HIGH_SPEED_15_PERCENTILE_INDEX`, 
     DAY(`hour_time_local`) AS `day_second_table` 

    FROM t.table_speed 
    WHERE (`hour_time_local` >= @datefrom) AND (`hour_time_local` < @dateto) AND (`traffic_id` = 'XXXXXXXX') 
    GROUP BY DAY(`hour_time_local`), MONTH(`hour_time_local`), YEAR(`hour_time_local`) 
) AS `second_table` ON `id` = `first_table`.`id` 

LEFT JOIN 
(
    SELECT 
     DAY(`hour_time_local`) AS `day_second_table`, 
     @timeset2 AS `timeset`, 
     IF(DAY(`hour_time_local`) != @previousDay2, @timeset2:=0, @timeset2:=1) AS ``, 
     @previousDay2 := DAY(`hour_time_local`), 
     IF(@timeset2 != 0, @rownumSecondTable:[email protected]+1, @rownumSecondTable:=1), 
     @rownumSecondTableAS `row_second_table`, 
     `hour_time_local` AS `hour_time_second_table`, 
     `ht_high_speed` AS `high_speed` 

    FROM t.table_speed, (SELECT @rownumSecondTableAS :=0) AS `third_table` 
    WHERE (`hour_time_local` >= @datefrom) AND (`hour_time_local` < @dateto) AND (`traffic_id` = '703170016-1') AND (`ht_high_speed` > 0) 
) AS `third_table` ON `id` = `first_table`.`id` 

WHERE (`hour_time_local` >= @datefrom) AND (`hour_time_local` < @dateto) AND (`traffic_id` = '703170016-1') AND (`low_speed` > 0) 

HAVING 
(
    ( 
     (`day` = `day_first_table`) AND (`day` = `day_second_table`) AND ((`row_first_table` = `LOW_SPEED_15_PERCENTILE_INDEX`) AND (`row_second_table` = `HIGH_SPEED_15_PERCENTILE_INDEX`)) 
    ) 
) 

ORDER BY `hour_time_local` ASC; 
+0

어떤 버전의 MySQL이 있습니까? 최신 버전에서는 파생 테이블에 대한 인덱스를 자동으로 만들 수 있습니다. 구형 버전은 비참하게 느립니다. 'EXPLAIN SELECT ... '그리고'SHOW CREATE TABLE'을 제공하십시오. –

답변

0

처음에는 이미 위의 문제에 대한 해결책을 찾았습니다. 향상된 쿼리는 아래에 설명 된 쿼리보다 훨씬 빠릅니다. 두 번째는 마지막 도움이되었지만 개선 되었으면 도움이 될 것입니다.

SET @timeset := 0; 
SET @timeset2 := 0; 
SET @previousDay := 0; 
SET @previousDay2 := 0; 
SET @datefrom = cast('2017-05-01 00:00:00' as datetime); 
SET @dateto = cast('2017-05-15 00:00:00' as datetime); 
SET @rownum_lt := 0; 
SET @rownum_ht := 0; 

SELECT 

    IF(DAY(`hour_time_local`) != @previousDay, @timeset:=0, @timeset:=1) AS ``, 
    @rownum_lt := IF(@timeset != 0, @rownum_lt:[email protected]_lt+1, @rownum_lt:=1) AS `row_low_speed`, 
    @previousDay := DAY(`hour_time_local`) AS ``, 

    `hour_time_local` AS `lt_hour_time_local`, 
    `hour_time_local_b`, 

    `LOW_SPEED_15_PERCENTILE_INDEX`, 
    `low_speed` AS `low_speed_a`, 

    `row_high_speed`, 
    `ht_hour_time_local`, 
    `HIGH_SPEED_15_PERCENTILE_INDEX`, 
    `high_speed` 

FROM unicam_stats.traffic_id_hour_stats_measured AS `hs` 

CROSS JOIN 
(
    SELECT 
     `hour_time_local` AS `ht_hour_time_local`, 
     `high_speed` AS `high_speed_ref`, 
     IF(DAY(`hour_time_local`) != @previousDay2, @timeset2:=0, @timeset2:=1) AS `b`, 
     @rownum_ht := IF(@timeset2 != 0, @rownum_ht:[email protected]_ht+1, @rownum_ht:=1) AS `row_high_speed`, 
     @previousDay2 := DAY(`hour_time_local`) AS `a`, 
     `hour_time_local_a`, 
     `HIGH_SPEED_15_PERCENTILE_INDEX` 

    FROM unicam_stats.traffic_id_hour_stats_measured AS `ht_hs` 

    LEFT JOIN 
    (
     SELECT 
      `hour_time_local` AS `hour_time_local_a`, 
      CEIL((15/100) * COUNT(high_speed)) AS `HIGH_SPEED_15_PERCENTILE_INDEX` 

     FROM unicam_stats.traffic_id_hour_stats_measured AS `ht_a` 
     WHERE (`hour_time_local` >= @datefrom) AND (`hour_time_local` < @dateto) AND (`traffic_id` = '703170016-1') 
     GROUP BY DAY(`hour_time_local`), MONTH(`hour_time_local`), YEAR(`hour_time_local`) 
    ) AS `ht_a` ON `id` = `ht_hs`.`id` 

    WHERE (`hour_time_local` >= @datefrom) AND (`hour_time_local` < @dateto) AND (`traffic_id` = '703170016-1') AND (`high_speed` > 0) 
    GROUP BY `hour_time_local`, `hour_time_local_a` 
    HAVING (`row_high_speed` = `HIGH_SPEED_15_PERCENTILE_INDEX` AND DAY(`ht_hour_time_local`) = DAY(`hour_time_local_a`)) 

) AS `ht` 

LEFT JOIN 
(
    SELECT 
     `hour_time_local` AS `hour_time_local_b`, 
     CEIL((15/100) * COUNT(low_speed)) AS `LOW_SPEED_15_PERCENTILE_INDEX` 

    FROM unicam_stats.traffic_id_hour_stats_measured AS `lt_a` 
    WHERE (`hour_time_local` >= @datefrom) AND (`hour_time_local` < @dateto) AND (`traffic_id` = '703170016-1') 
    GROUP BY DAY(`hour_time_local`), MONTH(`hour_time_local`), YEAR(`hour_time_local`) 

) AS `lt_a` ON `id` = `hs`.`id` AND `traffic_id` = `hs`.`traffic_id` 


WHERE (`hour_time_local` >= @datefrom) AND (`hour_time_local` < @dateto) AND (`traffic_id` = '703170016-1') AND (`low_speed` > 0) 
HAVING (`row_low_speed` = `LOW_SPEED_15_PERCENTILE_INDEX` AND DAY(`lt_hour_time_local`) = DAY(`hour_time_local_b`) AND DAY(`ht_hour_time_local`) = DAY(`hour_time_local_b`)) 
ORDER BY `hour_time_local`, `hour_time_local_b`, `ht_hour_time_local`