【发布时间】:2012-10-05 07:18:28
【问题描述】:
我想知道在使用 Yii 和 mysql 表时更好的方法(性能方面)是什么:
- 1 个包含所有列的表
- 具有外键关系的多个表(将列分布在它们之间)
基本上,我要问的是: 由于 Yii 会在查询时将所有对应的表都提取到对象中,所以当单个表有很多关系时,是否会导致性能下降?
一个更普遍的问题是:在处理 1 个与多个表和外键(再次是性能......)时,什么是好的做法和更聪明的方法?
【问题讨论】:
我想知道在使用 Yii 和 mysql 表时更好的方法(性能方面)是什么:
基本上,我要问的是: 由于 Yii 会在查询时将所有对应的表都提取到对象中,所以当单个表有很多关系时,是否会导致性能下降?
一个更普遍的问题是:在处理 1 个与多个表和外键(再次是性能......)时,什么是好的做法和更聪明的方法?
【问题讨论】:
如果性能是您设计策略中唯一的标准,您会选择 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)
);
【讨论】:
更好的选择是根据规范化规则正确设计数据库。 以下是一些关于它们的快速链接:
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 使用广泛的延迟加载,并且在您请求并使用它们之前不会加载相关元素。
【讨论】: