查询大表非常缓慢(有两个左连接表)

时间:2017-05-22 15:10:11

标签: mysql performance left-join

我想问一下下面这个查询怎么能更快地优化。无论如何,它对很多行来说都很慢。相同三个表的索引仍然不允许快速搜索非常大的表。对于任何建议,改进,我非常感谢。谢谢。

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 :=@rownumFirstTable +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:=@rownumSecondTable+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;

1 个答案:

答案 0 :(得分: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:=@rownum_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:=@rownum_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`