存储与计算聚合值

Ben*_*enV 104 mysql database-design aggregate

是否有任何指导方针或经验法则来确定何时存储聚合值以及何时动态计算它们?

例如,假设我有用户可以评分的小部件(请参阅下面的架构)。每次我显示一个小部件时,我都可以从Ratings表格中计算出平均用户评分。或者,我可以将平均评分存储在Widget表格中。这将使我不必在每次显示小部件时计算评分,但是每次用户对小部件进行评分时我都必须重新计算平均评分。

Ratings       Widgets
---------     -------
widget_id     widget_id
user_id       name              
rating        avg_rating  <--- The column in question
Run Code Online (Sandbox Code Playgroud)

Bri*_*ton 62

这取决于。预先计算聚合值会给写入带来更大的负载,推导它们会使读取更加困难

如果您经常访问派生值,则预计算是一个有效的反规范化步骤。但是,在这种情况下,我建议使用实体化视图(一种视图,写入磁盘,通过触发器链接到父表)。物化视图旨在存储经常询问但派生起来很乏味的数据,并且对于大量写入和少量读取很有用。

在高写入、高读取的场景中,考虑在后台执行一项模拟物化视图效果的任务,但不是实时的。这将呈现“足够好”的平均值,同时保持写入和读取性能。

在任何情况下,您都不应将派生列视为“普通”列:确保小部件“视图”中显示的数据存在于表中的其他位置,这样整个元组可以由您部署的任何进程派生。这个问题也与数据库(和数据库版本)有关,因此我建议针对正常大小的数据集和物化视图对聚合(具有适当的索引)进行性能测试。


Joe*_*Joe 11

您需要计算/显示与基础数字更改/更新频率相关的值的频率。

因此,如果您有一个每天有 10k 次点击的网站,该网站显示的值每小时只会更改一次,那么我会在基础值发生变化时进行计算(可能是数据库触发器,无论如何)。

如果您有一个工具可以查看统计数据,其中统计数据每秒都在发生变化,但您只有三个人可以访问,而且他们每天只能查看几次,那么我更有可能进行计算它在飞行中。(除非,首先需要花几分钟来计算出有过时的数据没什么大不了的......而且我的老板告诉我每小时只从 cron 生成一个东西,所以他没有等他想看的时候。)