【问题标题】:How to normalize my MySQL Database如何规范化我的 MySQL 数据库
【发布时间】:2017-02-25 11:34:24
【问题描述】:

我有 PHP/MYSQL 汽车租赁网站。在我存储的 MYSQL 表中

  1. 汽车牌照
  2. 汽车规格(如空调、品牌等)
  3. 每天的价格(30 列),因为 1 天的价格是每天 X 欧元,而 30 天的价格是每天 Y 欧元
  4. 每天的保险(这是每 汽车的事情,因为这取决于具体的汽车历史,年份, 品牌、型号等)。因此,由于一个月有 30 天,我们 这里还有 30 列,因为保险 1 天 保险 假设是 28 天

现在,如果我把所有这些东西都放进去,我将有大约 70 列。 有没有更聪明的方法来避免性能下降? 我不控制价格,也没有每日价格或每日保险公式。

一个想法是使用车牌作为索引并将其放入 2 张表中,一张带有价格(35 行),一张带有保险(35 行)。还有其他的吗?

DB 大约有 1000 辆汽车。我每天在数据库中收到大约 10.000 个查询

非常感谢。

【问题讨论】:

  • price per day (30 colums) ...如果您有超过 30 个日期,这将无法很好地扩展。相反,请按记录(行)更改日期。
  • 这个问题回答起来有点宽泛,有些事情还不清楚(至少对我来说)。但是,是的,规范化/关系数据库的一般想法是像您已经建议的那样创建单独的表。但是,一辆车最多只能租30天吗?我认为您需要仔细考虑每天的价格到底是什么意思。我无法想象一个月的天数是租车的限制因素。还是这样?
  • 1000 和 10000 以及 35 和 35*1000 是“小”数字。您没有任何大小/性能问题(假设您有合适的索引)。

标签: php mysql database-design


【解决方案1】:

要规范化数据库(或更一般地设计数据库),您必须清楚地确定您拥有的实体。

根据您的描述,您有以下四个实体:

  1. 汽车
  2. 规格
  3. 价格
  4. 保险

上面的每个实体都应该有一个表来处理它的属性(列)。

在定义实体之后,真正的规范化是通过键属性(列)或通过新实体(表)来定义实体之间的关系,例如在多对多关系中。让我们讨论一下关系:

  1. 汽车:一辆车应该有一个规格、价格和保险。即关系是一对一的。因此,cars 表应该具有与其他三个表相关联的 specification_id、price_id 和 insurance_id 列。

  2. 另一方面,其他三个表(实体:规格、价格和保险)可能有很多汽车,因此它与汽车的关系是一对多的,并且通过在汽车表中定义外键( specification_id、price_id 和 insurance_id)

它是如何工作的?

在插入新车之前,您必须完成其他实体。换句话说,所有可用的、规格、价格、保险的列表应该在可敬的表(实体)中找到,如果你有一辆没有任何定义的新车,那么你必须创建一个新的实体在插入或创建它之前覆盖它的需要。即插入汽车应该属于的新规格和/或新价格和/或新保险。

注意:这不是法律,您或其他人可能能够发明另一个实体的关系。但是,我在这里所考虑的是 基于关系数据库设计方法的一般提示

【讨论】:

  • 感谢大家的精彩回答!
  • 1 和 2 应该是一张表,因为规格是汽车本身的一部分,并且永久绑定到汽车的一个化身。
  • @Hafenkranich 我不这么认为,此类系统中的规范是可以通过其他实体共享的独立实体。例如,假设该机构有两辆相同的汽车,即两辆 BMW i7 型号 2015。您的意思是汽车实体特定的,例如电机和底盘编号,可以添加到汽车实体中。
  • 好的,我明白了。有道理。
【解决方案2】:

下面是一个快速的肮脏尝试。我会在专用表中移动价格和保险费用,每个表都有一个 car_iddays 字段。

Select brand,type,ac,seats FROM cars
LEFT JOIN prices ON cars.id = prices.car_id
LEFT JOIN insurence_costs ON cars.id = insurence_costs.car_id
WHERE
    licensePlate = 'HH-OH-234'
    AND prices.days = 28
    AND insurence_costs.days = 28

更新:添加了车牌。我只是把它们放在汽车规格中。一般来说,它们与汽车有关,但将来可能会改变。如果它们经常变化,我也宁愿将它们移到专用表中。

我实际上会节省每个租用日的价格,具体取决于数据库的整体租用跨度。这样,你可以做类似的事情

SELECT price FROM prices
WHERE car_id = 123 AND days = MAX(days);

这样,对于 30 天以上的租金,您可以将“最后”价格乘以实际租用天数。但这取决于定价定义。

【讨论】:

  • 截图来自MySQL Workbench
  • pricesinsurance_costs 结合起来可能是值得的,因为您几乎总是查看相同 天数的两个值? (具有两个数字列的单个表)
  • 不要使用FLOAT(m,2)——它涉及额外的舍入,可能会导致麻烦。更改为DECIMAL(m,2)
  • 好点@RickJames,DECIMAL 更合适,因为我们这里不是科学领域。
  • 在这个特定的用例中,我们可以合并两个表 pricesinsurence_costs。因为它们不属于一个严格的对象,所以无论如何我宁愿将它们放在单独的数据库表中。要么会有一个用例,我不需要其中一个数据部分,我可以节省一些处理时间。或者让我们想象一个用例,其中一个用户需要访问保险费用(内部计算),但另一个用户不应该能够查找它们。
猜你喜欢
  • 1970-01-01
  • 2011-12-16
  • 2013-07-17
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 2011-01-06
  • 2011-11-12
相关资源
最近更新 更多