SQL 个表的规范化
Normalization of SQL tables
我正在为一个项目创建一些 table,我刚刚意识到许多 table 具有相同的结构(Id、名称),但用于不同的事物。我应该在标准化方面走多远?我应该将它们全部构建成一个 table 还是将它们分开以便更好地理解?它如何影响性能?
示例 1:
TableObjectType(用于日志中的对象类型)
Id Name
1 User
2 MobileDevice
3 SIMcard
TableAction(用于日志中的操作类型)
Id Name
1 Create
2 Edit
3 Delete
TableStatus(用于设备可能具有的状态)
Id Name
1 Stock
2 Lost
3 Repair
4 Locked
示例 2:
表常量
Id Name
1 User
2 MobileDevice
3 SIMcard
4 Create
5 Edit
6 Delete
7 Stock
8 Lost
9 Repair
10 Locked
忽略命名,因为我的 table 有其他名字,但我使用这些是为了澄清。
对所有常量使用一个 table 的缺点是,如果我想稍后添加更多,它们不会真正进入 "groups",但另一方面 SQL 我在使用数据时不应该依赖特定的顺序。
我认为通常最好将 table 分开(这也有助于文档)。在某些特定情况下(您的选择...)您可以 "merge" 所有相似的 table 合并为一个(当然添加其他列,如 TAB_TYPE 以区分它们):这可能在开发应用程序和减少 table 的总数方面给你一些优势(这对你来说是个问题)。
如果都比较小table(记录不多),应该没有性能问题。
仅仅因为 table 具有与另一个相似的结构并不意味着它存储描述相同实体的数据。
有一些明显的原因不符合示例 2。
首先,您可能希望将 ObjectTypeID
列中的值限制为有效对象类型的值。执行此操作的明显方法是创建与 ObjectType
table 的外键关系。在 TableConstants
上创建类似的检查会困难得多(在大多数数据库引擎中,您不能以这种方式使用外键约束)。
其次,它使数据库能够自描述 - 检查模式的人会明白 "object type" 在您的业务领域中是一个有意义的概念。这对于长期存在的应用程序或具有大型开发团队的应用程序很重要。
第三,您通常会通过这些引用获得特定的业务逻辑 - 例如,"status" 通常需要一些逻辑来表示 "you can't modify a record in status LOCKED"。这种业务逻辑通常需要存储额外的数据属性——这对于 "Constants" table.
来说是不可能的
第四 - "constants" 必须进行管理。如果你有一个大模式,人们很快就会开始重新使用常量来反映略有不同的概念。您的 "create" 常量可能会应用于 table 存储业务请求以及您的日志事件。这变得几乎难以理解 - 如果业务决定日志事件不参考 "create" 而参考 "write",您的业务交易开始看起来都是错误的。
您可以做的是使用 ENUM(许多数据库引擎支持此)来模拟除了存储名称之外没有太多逻辑的属性。这消除了风险 1、2 和 4,但确实意味着您的逻辑在数据库架构中编码 - 添加新对象类型是架构更改,而不是数据插入。
我正在为一个项目创建一些 table,我刚刚意识到许多 table 具有相同的结构(Id、名称),但用于不同的事物。我应该在标准化方面走多远?我应该将它们全部构建成一个 table 还是将它们分开以便更好地理解?它如何影响性能?
示例 1:
TableObjectType(用于日志中的对象类型)
Id Name
1 User
2 MobileDevice
3 SIMcard
TableAction(用于日志中的操作类型)
Id Name
1 Create
2 Edit
3 Delete
TableStatus(用于设备可能具有的状态)
Id Name
1 Stock
2 Lost
3 Repair
4 Locked
示例 2:
表常量
Id Name
1 User
2 MobileDevice
3 SIMcard
4 Create
5 Edit
6 Delete
7 Stock
8 Lost
9 Repair
10 Locked
忽略命名,因为我的 table 有其他名字,但我使用这些是为了澄清。
对所有常量使用一个 table 的缺点是,如果我想稍后添加更多,它们不会真正进入 "groups",但另一方面 SQL 我在使用数据时不应该依赖特定的顺序。
我认为通常最好将 table 分开(这也有助于文档)。在某些特定情况下(您的选择...)您可以 "merge" 所有相似的 table 合并为一个(当然添加其他列,如 TAB_TYPE 以区分它们):这可能在开发应用程序和减少 table 的总数方面给你一些优势(这对你来说是个问题)。
如果都比较小table(记录不多),应该没有性能问题。
仅仅因为 table 具有与另一个相似的结构并不意味着它存储描述相同实体的数据。
有一些明显的原因不符合示例 2。
首先,您可能希望将 ObjectTypeID
列中的值限制为有效对象类型的值。执行此操作的明显方法是创建与 ObjectType
table 的外键关系。在 TableConstants
上创建类似的检查会困难得多(在大多数数据库引擎中,您不能以这种方式使用外键约束)。
其次,它使数据库能够自描述 - 检查模式的人会明白 "object type" 在您的业务领域中是一个有意义的概念。这对于长期存在的应用程序或具有大型开发团队的应用程序很重要。
第三,您通常会通过这些引用获得特定的业务逻辑 - 例如,"status" 通常需要一些逻辑来表示 "you can't modify a record in status LOCKED"。这种业务逻辑通常需要存储额外的数据属性——这对于 "Constants" table.
来说是不可能的第四 - "constants" 必须进行管理。如果你有一个大模式,人们很快就会开始重新使用常量来反映略有不同的概念。您的 "create" 常量可能会应用于 table 存储业务请求以及您的日志事件。这变得几乎难以理解 - 如果业务决定日志事件不参考 "create" 而参考 "write",您的业务交易开始看起来都是错误的。
您可以做的是使用 ENUM(许多数据库引擎支持此)来模拟除了存储名称之外没有太多逻辑的属性。这消除了风险 1、2 和 4,但确实意味着您的逻辑在数据库架构中编码 - 添加新对象类型是架构更改,而不是数据插入。