如何加速这个缓慢的查询

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

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

  1. SELECT
  2. cd.ParameterID,
  3. intervals.TimeStamp,
  4. intervals.GreenHouseID,
  5. intervals.TargetParam,
  6. intervals.ProductionID
  7. FROM
  8. (
  9. SELECT
  10. pd.TimeStamp,
  11. p.GreenHouseID,
  12. pd.ParameterID AS TargetParam,
  13. pd.ProductionID
  14. FROM
  15. Production p INNER JOIN
  16. ProductionData pd ON pd.ProductionID=p.ID
  17. GROUP BY
  18. pd.TimeStamp, p.GreenHouseID
  19. ) AS intervals,
  20. ClimateData cd
  21. WHERE
  22. DATE_FORMAT(intervals.TimeStamp,'%Y-%m-%d') = DATE_FORMAT(cd.Time_stamp,'%Y-%m-%d') AND
  23. cd.GreenHouseID = intervals.GreenHouseID
  24. GROUP BY
  25. intervals.ProductionID, intervals.TargetParam

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

  1. |id|select_type|table |partitions|type |possible_keys|key |key_len|ref |rows|filtered|Extra
  2. |1|PRIMARY |<derived2>|NULL |ALL |NULL |NULL |NULL |NULL | 416| 100.00|Using where Using temporary
  3. |1|PRIMARY |cd |NULL |ref |cd_ghid_idx |cd_ghid_idx |4 |intervals.GreenHouseID|1660| 100.00|Using where
  4. |2|DERIVED |p |NULL |index|PRIMARY |pr_gh_fk_idx |5 |NULL | 13| 100.00|Using index Using temporary
  5. |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 .. 主要性能问题如下:

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

它需要看起来更像

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

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

  1. DATE(pd.TimeStamp) AS TS_Date

那么,

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

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

  1. INDEX(GreenHouseID, TimeStamp) -- in this order

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

展开查看全部

相关问题