mysql - 对大型表(有两个左连接表)的查询结果非常慢

标签 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;

最佳答案

首先我想写一下,我已经找到了上面这些问题的解决方案。改进后的查询比下面描述的查询快得多。其次,我很感谢您最后的帮助,但任何改进和帮助都在这里受到欢迎。

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`

关于mysql - 对大型表(有两个左连接表)的查询结果非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44116436/

相关文章:

php - 动态下拉列表中的默认选择

MySQL:查询以获取数据库中每个表的计数?

java - 高效的排序数据结构,可以存储带有相应时间戳的原始消息

php - 使用 PHP + MySQL Left Join 合并来自 2 个查询的结果

mysql - 我可以将多个准备好的语句放入 MySQL 的一个存储过程中吗?

mysql - 为许多用户调整 MySql my.cnf

java - 使用单例或新对象实例有什么区别吗?

.net - .NET 程序集大小会影响性能吗?

MySQL LEFT JOIN 其中有多个值

mysql - 左外连接?行编号问题