如何加快这个慢查询

问题描述 投票:1回答:1

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

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服务器在我的笔记本电脑上(16GB RAM,CPU E3-1505M v5)。我没有对mysql设置进行任何更改。这会有用吗?

我希望在适当的时间内查询结果(在几分钟内就行了)。

谢谢。

mysql sql performance explain
1个回答
1
投票
  • 请为每个表提供SHOW CREATE TABLE,包括临时表。
  • 临时表上似乎有一个单列索引?
  • 温度与永久性应该在性能上没有差别。但是,创建临时表的额外步骤可能会造成损失。
  • 在适当的地方说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, ...;这没有意义,所以我无视它。

© www.soinside.com 2019 - 2024. All rights reserved.