查询或存储过程进行聚合查询?

时间:2017-01-13 12:00:33

标签: mysql mariadb

  • 我目前有一张600,000,000行的表。
  • 我想通过使用Group By子句对数据执行每日平均来减少报表应用程序的行数。

我的报告应用程序将使用较小的数据子集(减少99%)。

因为这将每天“建立”;什么是最好的工具 - 存储过程,查看或其他什么?

1 个答案:

答案 0 :(得分:1)

构建并维护一个Summary表。最初,您需要运行一个大GROUP BY来收集所有旧数据。之后,夜间工作会计算前一天的COUNT(*)SUM(...)等。

然后'报告'对这个新表格来说会跑得快得多。

该表的密钥包括日期(不是日期+时间),以及报告可能需要的几列。

Blog with more details

我发现典型的加速比是10倍;你可能得到100倍(减少99%)。

最好的工具是您通过cron(或者MySQL EVENT)运行的脚本。它只会做类似

的事情
INSERT INTO SummaryTable (dy, ..., ct, tot, ...)
SELECT DATE(datetime), ...,   -- key
       COUNT(*), SUM(..), ...   -- data
   FROM FactTable
   WHERE datetime >= CURDATE() - INTERVAL 1 DAY
     AND datetime  < CURDATE();

可能只需要一个SQL语句。是的,它可能存在于存储过程中,但与直接在夜间脚本中直接存在差别不大。

在某些情况下,最好使用INSERT ... ON DUPLICATE KEY UPDATE ... SELECT ...(但这会变得混乱)。

在谈论&#34;平均值&#34;时,请考虑以下因素:

  • 每日平均值可以每晚计算:AVG(...),但
  • 应该计算月度平均值,而不是每日平均值,而是来自SUM(daily_sums) / SUM(daily_counts)。也就是说,摘要表可能需要COUNT(*)SUM(...)

要最初填充此摘要表,我会编写一次性脚本,以便一次一天地慢慢浏览600M行。当然,你可以一次完成所有工作,但是对其他一切的干扰可能会很糟糕。

更好的是夜间脚本将代码包含在&#34;拾取它停止的位置&#34;。这样,如果脚本在某个晚上无法运行,它将在第二天晚上修复遗漏。或者,当您发现问题时,可以手动运行它。额外的跑步不会伤害任何事情。

当您参与其中时,请考虑您可能需要的其他摘要表。我通常发现数据仓库应用程序需要3-7个汇总表。另一方面,请记住,每日摘要表可以(足够有效地)推导出每周和每月摘要。在一些情况下,我有一个关于一件事的每小时汇总表,然后是每日表,用于不同的事情。

600M行很大。将会老&#39;数据被清除?一旦你有了所需的汇总表,那么旧的&#39;不再需要数据? Blog on using Partitioning for such