Sql 简单表格设计问题
我试着提前一点思考,如果可能的话,尽量避免额外的痛苦 我在过去的应用程序中遇到过这个问题,通常会选择最详细的方法,但我想听听其他一些人的意见 如果您有一个如下所示的基本表,那么是否明智和/或更高效地包含一个字段,该字段包含根据其他两列中的信息进行计算的结果。即:Sql 简单表格设计问题,sql,ruby-on-rails,database-design,postgresql,Sql,Ruby On Rails,Database Design,Postgresql,我试着提前一点思考,如果可能的话,尽量避免额外的痛苦 我在过去的应用程序中遇到过这个问题,通常会选择最详细的方法,但我想听听其他一些人的意见 如果您有一个如下所示的基本表,那么是否明智和/或更高效地包含一个字段,该字段包含根据其他两列中的信息进行计算的结果。即: +-----+---------+------------+-------+--------+-------+ | id | room_id | bookdate | price | people | total | +-----
+-----+---------+------------+-------+--------+-------+
| id | room_id | bookdate | price | people | total |
+-----+---------+------------+-------+--------+-------+
| 414 | 132 | 2010-03-01 | 14.55 | 2 | 29.10 |
| 415 | 132 | 2010-03-02 | 14.55 | 2 | 29.10 |
| 416 | 132 | 2010-03-03 | 14.55 | 2 | 29.10 |
+-----+---------+------------+-------+--------+-------+
最后一个字段中的信息可以从前两个字段的乘积中提取,因此它是多余的,不必要的。是否还有值得拥有的实例?可以创建一个包含除最后一个字段以外的所有字段的表,然后创建一个包含所有字段并自动统计最后一个字段的视图 因此,表将只包含这些字段
+-----+---------+------------+-------+--------+
| id | room_id | bookdate | price | people |
+-----+---------+------------+-------+--------+
| 414 | 132 | 2010-03-01 | 14.55 | 2 |
计算总量的视图的定义也很简单:
select *, price*people as total from rooms
(假设您的表被称为
rooms
作为经验法则,我不会动态存储可以计算的值(特别是可以轻松计算的值),除非存在性能问题并且我需要节省一些处理时间
这是性能和存储之间的一个经典折衷。我建议在需要性能提升之前计算该值。我会继续,并将其放在总数字段中。从这里我可以看到,没有“折扣”或类似字段可能会减少总数,但我可以想象这样的情况:价格*人数可能不等于总数。您可能需要考虑一个注释字段或甚至一个表来允许某人注意<强>为什么强>总数与其他字段的乘积不匹配。
分享和享受。一般规则是,你不应该存储你可以轻松计算的内容,但是如果你通过分析你的应用程序而不是猜测来确定这一领域是性能瓶颈,那么就去做。基本上我不希望有“总计”字段,或由其他字段计算的任何字段,不在同一个表中,也不从其他表中计算。 如果价格字段将发生更改,则可能有人“忘记”更新“总计”字段,您将得到错误的数据 使用此字段可以很容易地进行选择: 从一些表格中选择价格、人员、(价格*人员)作为总计 唯一的情况是,我想保留一个计算字段是可以的,因为它需要很长的时间来计算,并且会在大量数据上使数据库过载
BR通常认为,存储可以从表中的其他字段简单计算的字段是一种不好的做法。我建议您只在需要存储复杂计算结果时使用它,并且存储计算值比每次重新计算值更容易-但是在您的情况下这似乎没有必要
计算字段的另一个问题是,可以在不修改存储结果的情况下更改用于计算的原始值,从而在应用程序中造成潜在问题。如果您这样做是为了方便编写查询,我将创建一个包含总计的视图 否则,这是一个问题。有时表的非规范化是可以接受的,特别是在数据仓库这样的环境中,可以用来提高性能。但是,确保数据保持一致是很重要的。换句话说,您需要确保在
价格时更新总计
字段代码>或人员
更改
在实践中,我认为这是最后的选择,只在其他性能优化不足时使用。此外,非正规化不能保证改进——根据数据和其他因素的数量,它实际上会使事情变得更糟。
注:表格不能是3NF(第三范式)直到计算字段被删除。因为您可以计算值——在这种情况下很容易——它是冗余的。您几乎不应该存储冗余数据。这意味着,您更新价格或人员的每个地方,都必须确保更新总计。如果您甚至忘记在一个地方进行此操作,则数据现在是不一致的。因此假设你现在有一个记录,上面写着price=$10,people=3,total=$40。如果你有不同的程序以不同的方式显示信息——不同的总数或子集,或者其他什么——用户可能会根据他问同一个问题的方式得到不同的答案。虽然得到错误的答案不好,但有时得到错误的答案更糟糕一个正确的答案,有时是错误的答案,因为可能不清楚如何解决问题。我的意思是,如果我看到某个客户在他应该显示3的时候显示了2个人,大概我可以去某个屏幕,用3改写2,单击“保存”或其他什么,它就被修复了。但是如果它说$10乘以2个人=30,我该去哪里修好它?怎么修好
你可能会说记录只在一个地方更新,所以没有问题。但那是今天。如果明天你或其他程序员添加一个新函数来进行不同类型的更新呢
我现在正在开发一个充满冗余数据的系统。关于我们公司每个产品的基本信息都存储在一个“项目”中表。对于每个库存单位,我们都有一个库存记录,而不是简单地引用项目记录,他们复制每个库存单位的所有数据。当一个项目售出时,我们将所有数据复制到销售记录中。如果有东西被退回,我们将所有数据复制到退货记录中。对于其他几种记录类型,等等。这会导致无休止的麻烦e、 我们曾经遇到一个问题,用户运行一个查询,查找具有某些特征的项目,并且点击列表中包含不符合搜索条件的项目。为什么?因为查询会查找所有符合搜索条件的项目记录,所以会尝试
create table rooms (
price numeric,
people numeric,
total numeric check (total=price*people));