0

我正在研究一个带有 3 个表的 MySQL 数据库 - 锻炼数据、练习和设置表。我面临与基于这三个表生成报告相关的问题。

要添加更多信息,一组练习组成一个练习,而一些练习将是一个锻炼。我目前拥有要从这些表中的数据生成报告的指标。我必须生成包括本周在内的过去 42 天的报告。当我通过加入这些表获得报告时,查询运行了很长时间。

例如 - sets 表在过去 42 天内有超过 100 万条记录。此表中的 id 是 excercise 表中的 excercise_id。excercise 表的 id 是锻炼数据表中的锻炼 ID。

我正在运行这个查询,获取数据需要 10 多分钟。我必须准备一份报告并在浏览器中显示给用户。但是由于这个长时间运行的查询,网页超时并且用户无法看到报告。

关于如何实现这一目标的任何建议?

        SELECT REPORTSETS.USER_ID,REPORTSETS.WORKOUT_LOG_ID,
               REPORTSETS.SET_DATE,REPORTSETS.EXCERCISE_ID,REPORTSETS.SET_NUMBER 
          FROM EXCERCISES 
    INNER JOIN REPORTSETS ON EXCERCISES.ID=REPORTSETS.EXCERCISE_ID 
         where user_id=(select id from users where email='testuser1@gmail.com') 
           and substr(set_date,1,10)='2013-10-29' 
      GROUP BY REPORTSETS.USER_ID,REPORTSETS.WORKOUT_LOG_ID,
               REPORTSETS.SET_DATE,REPORTSETS.EXCERCISE_ID,REPORTSETS.SET_NUMBER
4

4 回答 4

1

对您可能想要查看的 SQL 的评论:

1) 你有关于 USER_ID 和 SET_DATE 的索引吗?

2) SET_DATE 的数据类型看起来不对,是 varchar 吗?将其存储为日期意味着数据库可以更有效地优化您的搜索。目前,每个查询都会无数次调用 substring 方法,因为它必须针对 where 子句第一部分返回的每一行运行。

3) group by 真的需要吗?除非我遗漏了某些东西,否则声明的“分组依据”部分不会带来任何好处;)

于 2013-11-01T13:52:30.563 回答
1

两件事情:

首先,您有以下 WHERE 子句项来提取一天的数据。

  AND substr(set_date,1,10)='2013-10-29'

这明确地破坏了日期索引的使用。如果您的set_date列具有DATETIME数据类型,那么您想要的是

  AND set_date >= `2013-10-09`
  AND set date <  `2013-10-09` + INTERVAL 1 DAY

这将允许对 set_date 上的索引使用范围扫描。在我看来,您可能想要一个复合索引(user_id, set_date)。但是你应该EXPLAIN弄明白这是否正确。

其次,你在滥用GROUP BY. 该子句毫无意义,除非您在查询中具有某种汇总功能,例如SUM()or GROUP_CONCAT()。你想要ORDER BY吗?

于 2013-11-01T13:57:38.180 回答
0

如果您可以将日期存储为日期,或者以您需要进行比较的格式存储,它应该会产生显着差异。在每个日期执行 substr() 调用必须非常耗时。

于 2013-11-01T13:52:06.733 回答
-1

当然,调整查询的建议将有助于提高查询速度。但我认为这里的重点是在会话超时之前可以用超过 100 万条记录做什么。如果您有 2 或 3 百万条记录,那么一些性能调整会解决问题吗?我不这么认为。所以:

1)如果要在浏览器上显示,请使用分页和查询(例如)前 100 条记录。
2)如果要生成报告(如pdf),则使用异步方法(JMS)

于 2013-11-01T13:44:17.907 回答