单列

时间:2017-01-26 15:01:34

标签: mysql database database-design relational-database

这是关于数据库设计的问题。假设我有几个表,其中一些表都有一个共同的到期字段。

CREATE TABLE item (
    id INT PRIMARY KEY
)

CREATE TABLE coupon (
    id INT PRIMARY KEY FOREIGN KEY (`item.id`),
    expiry DATE NOT NULL
)

CREATE TABLE subscription (
    id INT PRIMARY KEY FOREIGN KEY (`item.id`),
    expiry DATE NOT NULL
)

CREATE TABLE product(
    id INT PRIMARY KEY FOREIGN KEY (`item.id`),
    name VARCHAR(32)
)

到期列确实需要编入索引,以便我可以在到期时轻松查询。

我的问题是,我应该将到期列拖到另一个表中吗?

CREATE TABLE item (
    id INT PRIMARY KEY
)

CREATE TABLE expiry(
    id INT PRIMARY KEY,
    expiry DATE NOT NULL
)

CREATE TABLE coupon (
    id INT PRIMARY KEY FOREIGN KEY (`item.id`),
    expiry_id INT NOT NULL FOREIGN KEY(`expiry.id`)
)

CREATE TABLE subscription (
    id INT PRIMARY KEY FOREIGN KEY (`item.id`),
    expiry_id INT NOT NULL FOREIGN KEY(`expiry.id`)
)

CREATE TABLE product(
    id INT PRIMARY KEY FOREIGN KEY (`item.id`),
    name VARCHAR(32)
)

另一种可能的解决方案是将到期时间延长到另一个基地" class"表

CREATE TABLE item (
    id INT PRIMARY KEY
)

CREATE TABLE expiring_item (
    id INT PRIMARY KEY FOREIGN KEY(`item.id`),
    expiry DATE NOT NULL
)

CREATE TABLE coupon (
    id INT PRIMARY KEY FOREIGN KEY (`expiring_item .id`),
)

CREATE TABLE subscription (
    id INT PRIMARY KEY FOREIGN KEY (`expiring_item .id`),
)

CREATE TABLE product(
    id INT PRIMARY KEY FOREIGN KEY (`item.id`),
    name VARCHAR(32)
)

鉴于数据库的性质,重构表结构一旦使用就很困难,我无法权衡每种方法的优缺点。

从我看到的,第一种方法使用最少数量的表连接,但是,我将为每个过期项目提供冗余数据。第二种方法似乎很好,因为任何时候我需要为一个项添加一个到期时我只需要向该表添加一个外键。但是,如果我发现过期的项目(或过期项目的子集)实际上共享另一个属性,那么我需要为此添加另一个表。我最喜欢第三种方法,因为它使我最接近OOP,如层次结构。但是,我担心这是我对OOP编程的个人偏见,并且数据库表不像OOP类继承那样使用组合。

提前抱歉SQL语法不好。

2 个答案:

答案 0 :(得分:0)

我坚持使用第一种设计,因为“冗余”数据仍然是有效数据,如果仅作为某个时间点有效的记录,它还允许以最小的影响进行更新。此外,第二个选项没有多大意义,因为到期是一个在表引用之外没有真实上下文的arbritrary项,换句话说,除非它与优惠券或订阅相关联,否则它是一个孤儿值。最后,第三个选项在一个项目到期的什么时候变得没有意义了?一旦定义?在到期前的一段时间内...在当天结束时,到期日是一个独特的属性,恰好与优惠券和订阅具有相同的名称和目的但是彼此无关或因此而项目

答案 1 :(得分:0)

规范化“连续”值,例如datetime,float,int等。在expiry上进行任何类型的范围测试都会非常低效。

无论如何,DATE需要3个字节; INT需要4,因此更改会增加磁盘占用空间。

所以,使用第一个,而不是第二个。但...

至于第三个,你说“到期是独立的”,但你建议有一个expiry ??这是什么?

如果他们不是独立的,那么另一个原则就会发挥作用。 “数据库中没有冗余数据。”因此,如果相同的 expiry确实适用于多个连接表,则它应该只在其中一个表中。然后第三个架构是最好的。 (例外:可能存在性能问题,但我对此表示怀疑。)

如果优惠券/订阅/等有不同的日期,那么您不能使用第三个。