多个SQL表和外键

时间:2012-10-05 07:18:29

标签: php mysql pdo yii

我想知道使用Yii和mysql表时哪种方法更好(性能明智):

  1. 包含所有列的1个表
  2. 多个表(使用外键关系分配列)
  3. 基本上,我要问的是: 当一个表有很多关系时是否有任何性能下降,因为Yii会在你进行查询时将所有相应的表提取到对象中?

    一个更普遍的问题是:在处理1对多个表和外键(再次表现......)时,什么是好的做法和更聪明的方法。

2 个答案:

答案 0 :(得分:3)

如果性能是您设计策略中唯一的标准,那么您会选择1.一个非常糟糕的选择,这会在您的问题的后期阶段给您带来很多问题。

数据库的设计应考虑到规范化,因此毫无疑问,您必须选择选项2!

<强>更新

规范化和未规范化的示例:假设我们有一个带DVD租借的表,并且想要跟踪谁租借了DVD:

平台:

CREATE TABLE DVD (
  DvdId INT NOT NULL AUTO_INCREMENT, 
  DvdTitle varchar(64),
  Rental1 varchar(64), 
  Rental2 varchar(64), 
  Rental3 varchar(64),
  Primary Key(DvdId)
);

有3个出租条目的空间,之后有麻烦。除此之外,当客户的电话号码需要额外的字段时,必须增加3个字段。

第一步规范化:

CREATE TABLE DVD (
  DvdId INT NOT NULL AUTO_INCREMENT, 
  DvdTitle varchar(64),
  Primary Key(DvdId)
);

CREATE TABLE Rentals (
  RentalId INT NOT NULL AUTO_INCREMENT, 
  DvdId INT NOT NULL, 
  CustomerName varchar(64),
  RentalDate DateTime,
  Primary Key(RentalId)
);

这样更好,但仍未完全正常化。如果客户两次租用相同的DVD,该怎么办?然后在租赁表中会有一个双重客户条目。

决赛:

CREATE TABLE DVD (
  DvdId INT NOT NULL AUTO_INCREMENT, 
  DvdTitle varchar(64),
  Primary Key(DvdId)
);

CREATE TABLE Rentals (
  RentalId INT NOT NULL AUTO_INCREMENT, 
  DvdId INT NOT NULL, 
  CustomerId INT NOT NULL, 
  RentalDate DateTime,
  Primary Key(RentalId)
);

CREATE TABLE Customers (
  CustomerId INT NOT NULL AUTO_INCREMENT, 
  CustomerName varchar(64),
  Primary Key(CustomerId)
);

答案 1 :(得分:1)

更好的选择是正确设计数据库遵守规范化规则。 以下是一些关于它们的快速链接:

http://databases.about.com/od/specificproducts/a/normalization.htm

http://moryadesigns.wordpress.com/2009/09/08/rules-of-data-normalization-sql/

1NF 消除重复组 - 为每组创建一个单独的表 相关属性,并为每个表提供一个主键。

2NF 消除冗余数据 - 如果属性仅依赖于部分属性 多值密钥,将其删除到单独的表中。

3NF 消除不依赖于键的列 - 如果属性不依赖 有助于对密钥的描述,将它们删除到一个单独的表中。

BCNF Boyce-Codd Normal Form - 如果候选键之间存在非平凡的依赖关系 属性,将它们分成不同的表。

4NF 隔离独立的多个关系 - 没有表可能包含 两个或多个1:n或n:m关系不直接相关。

5NF 隔离语义相关的多个关系 - 可能有 对信息的实际约束,证明分离逻辑上相关的多对多是合理的 关系。

ONF 最佳范式 - 仅限于简单(元素)的模型 事实,如对象角色模型表示法所表达的。

DKNF Domain-Key Normal Form - 一个没有任何修改异常的模型。

Yii使用广泛的延迟加载,并且在您要求并使用它们之前不会加载相关元素。