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

Php MySQL-动态计算字段与存储计算数据,php,mysql,field,Php,Mysql,Field,如果以前有人问过这个问题,我很抱歉,但是我似乎找不到关于动态计算和在数据库中存储字段的问题的答案 我读了几篇文章,其中建议最好在可以计算的时候进行计算,但我想知道这是否仍然适用于以下两个示例 例1。假设您正在存储与汽车相关的数据。您存储的燃油箱大小以升为单位,以及每100公里使用的升数。你还想知道它可以行驶多少公里,这可以根据油箱的大小和经济性来计算。我看到了两种方法: 添加或更新车辆时,计算公里数并将其作为静态字段存储在数据库中 每次进入车辆时,计算行驶中的公里数 因为汽车的经济性/油箱尺寸不

如果以前有人问过这个问题,我很抱歉,但是我似乎找不到关于动态计算和在数据库中存储字段的问题的答案

我读了几篇文章,其中建议最好在可以计算的时候进行计算,但我想知道这是否仍然适用于以下两个示例

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

  • 添加或更新车辆时,计算公里数并将其作为静态字段存储在数据库中
  • 每次进入车辆时,计算行驶中的公里数
  • 因为汽车的经济性/油箱尺寸不会改变(尽管可以编辑),所以KMs是一个相当静态的值。我不明白为什么每次进入汽车时我们都要计算它。这会不会浪费cpu时间,而不是简单地将其存储在数据库中的单独字段中,并仅在添加或更新汽车时进行计算

    我的下一个例子,几乎是一个完全不同的问题(但在同一个主题上),涉及数数儿童

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

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

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

    提前感谢,


    Christian

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

    在这两个示例中,您谈论的值都是静态的,计算静态值只是胡说八道。此外,如果我们假设表的查询量大于更新量,那么计算数据也会降低性能。

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

    对于您的第一个示例,没有理由有一天会有人改变计算KMs的方式。我会将其存储在数据库中(通过触发器或通过insert/update上的PHP——因为MySQl触发器……它们……不如其他一些DB触发器好)

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


    请注意,MySQl还提供了一个很好的查询缓存,这将防止同一查询计算过多。

    其他人已经谈到了技术方面,所以让我给您另一个观点来考虑:

    对于您引入的每一个异常,您都会使开发过程变慢

    非规范化数据、聚合、预连接数据等都是使开发变得非常复杂的例子,因为您必须:

    • 无论何时更改详细表,都要不断重写聚合逻辑
    • 测试更多(通常是应用程序中看似不相关的部分)
    • 写更多的文档
    • 使升级和修补程序复杂化

    在许多情况下,这是值得的,而且在某些情况下是绝对必要的,但如果您不必牺牲开发速度,那将是非常愚蠢的

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

    • 如果操作规则改变怎么办?例如,添加TVA
    • 您的数据库将很难维护。因为,每次更改其结构时,如果它影响计算字段,则必须重新计算所有内容
    事实上,除非您需要优化,否则不应该这样做。这里有一些很好的相关讨论: