MySQL - 动态计算字段与存储计算数据

时间:2010-12-22 11:28:25

标签: php mysql field

如果以前曾经问过这个问题,我很抱歉,但我似乎无法找到一个问题的答案,这个问题与我在飞行中计算数据库中的存储字段有关。

我读了一些文章,建议你什么时候可以计算,但我想知道这是否仍适用于以下2个例子。

示例1.假设您正在存储与汽车相关的数据。您将油箱尺寸以升为单位存储,以及每100公里使用多少升油箱。您还想知道它可以行驶多少KM,这可以根据油箱尺寸和经济性来计算。我看到了两种方法:

  1. 添加或更新汽车时,计算KM的数量并将其存储为数据库中的静态字段。
  2. 每次访问汽车时,都要计算动态的KM数量。
  3. 因为汽车经济性/坦克尺寸没有变化(尽管可以编辑),KMs是一个非常静态的价值。我不明白为什么我们会在每次访问汽车时计算它。这不会浪费cpu时间,而不是简单地将其存储在数据库中的单独字段中,并仅在添加或更新汽车时计算?

    我的下一个例子,几乎是一个完全不同的问题(但在同一主题上),与计算儿童有关。

    假设我们有一个包含类别和项目的应用。我们有一个视图,我们显示所有类别,以及每个类别中所有项目的计数。再一次,我想知道什么更好。要在每次访问页面时执行MySQL查询来计算每个类别中的所有项目?或者将计数存储在类别表的字段中,并在添加/删除项目时更新?

    我知道存储任何可以计算的内容都是多余的,但我担心计算字段或计数记录可能会比将数据存储在字段中要慢。如果不是那么请告诉我,我只想了解何时使用这两种方法。在一个小规模上,我想这两种方式无关紧要,但像Facebook这样的应用程序,他们是否真的会计算每次有人查看您的个人资料时您拥有的朋友数量,还是只将其存储为一个字段?

    我很感激对这两种情况的任何回应,以及可能解释计算与存储的好处的任何资源。

    提前致谢,

    基督教

5 个答案:

答案 0 :(得分:12)

在数据库中引入冗余是一种有效的优化方法。与所有优化一样,除非您确认这是瓶颈实际存在的地方,否则不要这样做。

答案 1 :(得分:8)

有一点需要注意的是您使用数据的方式。 如果您的应用程序中的多个应用程序或多个层(可能是旧代码和同一应用程序中的新代码)正在访问您的数据,则可以通过在数据库中预先计算来降低计算错误的风险。然后,无论哪个应用程序请求它,您的计算数据将始终相同。

对于你的第一个例子,没有理由有一天某人必须改变你的KM需要计算的方式。我会将它存储在数据库中(通过触发器或通过PHP插入/更新 - 因为MySQl触发器......好吧它们......不如其他一些数据库触发器好)。

现在,如果我们采用你的第二个例子,那么真的不确定有人会在某一天为这些类别计算添加一些过滤器。例如,只接受介于2和5之间的子项。然后,所有预先计算的结果都不起作用。 如果你需要对这些东西进行一些优化和缓存,它可能更像是你需要的应用程序层缓存,比如memcache,或者存储在缓存表中的预先计算结果。但是这个缓存是一个应用程序缓存,它以某种方式与您的应用程序参数相关(具有不同过滤器的请求将在缓存中使用不同的记录)。

请注意,使用MySQl,您还可以获得一个很好的查询缓存,这将阻止同样的查询计算得太多。

答案 2 :(得分:8)

其他人已经涉及技术方面,所以让我给你另一个考虑的观点:

对于您介绍的每个异常情况,您的开发过程都会变慢。

非规范化数据,聚合,预先加入的数据等等都是使开发变得非常复杂的例子,因为你必须:

  • 每当您更改详细表格时,请继续重写聚合逻辑
  • 测试更多(通常看似无关的应用程序部分)
  • 撰写更多文档
  • 使升级和修补程序复杂化

在许多情况下,它是值得的,在某些情况下是绝对必要的,但如果你不必要的话,牺牲开发速度将是非常愚蠢的。

答案 3 :(得分:1)

在这两个示例中,您所谈论的值都是静态的,计算静态值只是一个废话。此外,如果我们假设表的查询次数多于更新,则计算数据也会导致性能下降。

答案 4 :(得分:1)

为什么应避免在表中存储计算字段:

  • 如果操作规则发生变化怎么办?例如,您添加TVA
  • 您的数据库将很难维护。因为,每次更改其结构(如果它影响到计算字段)时,您都必须重新计算所有内容