如何加速这个缓慢的查询

rxztt3cl  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(362)

我设计了一个mysql数据库并加载了一些数据(总共可能有1000万行)。我试图从两个时间间隔重叠的表中获取数据。

SELECT 
        cd.ParameterID,
        intervals.TimeStamp,
        intervals.GreenHouseID,
        intervals.TargetParam,
        intervals.ProductionID
FROM
        (
                SELECT 
                        pd.TimeStamp, 
                        p.GreenHouseID, 
                        pd.ParameterID AS TargetParam, 
                        pd.ProductionID
                FROM 
                        Production p INNER JOIN 
                        ProductionData pd ON pd.ProductionID=p.ID
                GROUP BY
                        pd.TimeStamp, p.GreenHouseID
        ) AS intervals,
    ClimateData cd
WHERE
        DATE_FORMAT(intervals.TimeStamp,'%Y-%m-%d') = DATE_FORMAT(cd.Time_stamp,'%Y-%m-%d') AND
        cd.GreenHouseID = intervals.GreenHouseID
GROUP BY
        intervals.ProductionID, intervals.TargetParam

不幸的是,查询花费的时间太长(我还没有看到它完成)。
当我使用 EXPLAIN 我得到以下结果:

|id|select_type|table     |partitions|type |possible_keys|key          |key_len|ref                   |rows|filtered|Extra
|1|PRIMARY     |<derived2>|NULL      |ALL  |NULL         |NULL         |NULL   |NULL                  | 416|  100.00|Using where Using temporary
|1|PRIMARY     |cd        |NULL      |ref  |cd_ghid_idx  |cd_ghid_idx  |4      |intervals.GreenHouseID|1660|  100.00|Using where       
|2|DERIVED     |p         |NULL      |index|PRIMARY      |pr_gh_fk_idx |5      |NULL                  |  13|  100.00|Using index Using temporary
|2|DERIVED     |pd        |NULL      |ref  |pd_pr_fk_idx |pd_pr_fk_idx |5      |ghdb.p.ID             |  32|  100.00|NULL

我相信我把索引放在所有相关的列上,以确保快速查询。我设计的查询使用一个临时表( intervals )然而。这是在贬低表演吗?如果是这样,如何设计一个更快的查询?
mysql服务器在我的笔记本电脑上(16GBRAM,cpu e3-1505MV5)。我没有对mysql设置做任何更改。那有用吗?
我想在适当的时间查询结果(在几分钟内就可以了)。
谢谢您。

ylamdve6

ylamdve61#

请提供 SHOW CREATE TABLE 对于每个表,包括临时表。
temp表上似乎只有一列索引?
临时性和永久性应该在性能上没有区别。但是,创建temp表的额外步骤可能会付出代价。
NOT NULL 在适当的情况下。
在函数调用中隐藏列( DATE_FORMAT 在您的例子中)防止使用索引—因此 ALL .
您不能“调整您的方式以解决性能问题”,因此我将不讨论调整,而只是询问 innodb_buffer_pool_size .
请不要使用“逗号连接”;相反,使用 JOIN .. ON .. 主要性能问题如下:

WHERE DATE_FORMAT(intervals.TimeStamp,'%Y-%m-%d') = 
      DATE_FORMAT(cd.Time_stamp,'%Y-%m-%d')
  AND cd.GreenHouseID = intervals.GreenHouseID

它需要看起来更像

WHERE intervals.TimeStamp ...
  AND cd.GreenHouseID = intervals.GreenHouseID

既然你要努力建造 intervals 在飞行中,有一列只包含日期。你也可以通过 DATE(...) 而不是 DATE_FORMAT(...) .
由于您正在计算其中一个日期,请更改 pd.TimeStamp

DATE(pd.TimeStamp) AS TS_Date

那么,

WHERE intervals.TimeStamp >= cd.TS_Date
  AND intervals.TimeStamp  < cd.TS_Date + INTERVAL 1 DAY
  AND intervals.GreenHouseID = cd.GreenHouseID

你还需要把这个“综合”索引放在一起 intervals :

INDEX(GreenHouseID, TimeStamp) -- in this order

我明白了 GROUP BY pd.TimeStamp, ... ; 这没有道理,所以我忽略它。

相关问题