18

设计数据库时要记住哪些重要事项?

我不想限制您对我的需求的回答,因为我相信其他人也可以从您的见解中受益。但我正在为多客户社区驱动的网站规划一个内容管理系统。

4

23 回答 23

40

“规范化,直到它受伤;去规范化,直到它起作用。”

于 2008-09-26T18:32:31.727 回答
21

(假设 OLTP)

数据结构的规范化。(性能反规范化通常可以在需要时进行)

http://en.wikipedia.org/wiki/Database_normalization

于 2008-09-26T18:29:20.547 回答
15

确保使用约束(CHECKNOT NULLFOREIGN KEYPRIMARY KEYDEFAULT)首先确保只有正确的数据存储在数据库中。您总是可以购买更快的硬件,但您无法购买更多正确的数据。

于 2008-09-26T18:49:06.193 回答
15

预先建立一致的命名标准。从长远来看,这将节省几分钟不必要的思考。(这可能读起来很讽刺,但我是认真的。)

并且不要缩写任何东西,除非它非常常见。不要将数据库变成车牌信息猜谜游戏。令人惊讶的是,一年后变得不明显。

于 2008-09-26T19:13:59.253 回答
9

尝试想象您将针对它执行的 SQL 查询。

这很重要,因为你会做很多!

于 2008-09-26T18:40:12.347 回答
7

有些事情我会记住。确保每个表都有唯一标识记录的方法(这样做可以节省数小时的痛苦)。规范化但不要加入大型多列自然键,除非您希望整个过程变慢。请改用在父表中自动生成的数字键。

是的,考虑一下您需要运行的查询和报告类型。考虑可扩展性。看起来您在订单表中不需要超过 10 个产品列,但是当您需要 11 个时会发生什么。最好有一个订单表和一个订单详细信息表。

确保将所有数据完整性规则合并到数据库中。并非所有数据更改都来自用户界面,我不得不尝试修复太多严重混乱的数据库,因为设计人员认为将所有规则都放在 GUI 中是可以的。

设计时要考虑的最关键的事情首先是如何确保数据完整性(如果数据没有意义,那么数据库就没有用处),其次是如何确保性能。不要使用对象模型来设计关系数据库,除非你想要糟糕的性能。

下一个最重要的事情是数据保护和安全。用户永远不应该直接访问数据库表。如果您的设计需要动态 SQL,他们将必须具有该访问权限。从通过 SQL 注入攻击之类的潜在黑客入侵的角度来看,这很糟糕,但更重要的是,它会为内部人员进行欺诈打开您的数据库。是否有需要加密数据的字段(信用卡信息、密码和社会安全号码是永远不应该以未加密方式存储的项目之一)。您打算如何做到这一点以及您打算如何审核解密以确保人们在不需要查看数据时不会解密。有没有你必须经历的法律障碍(HIPPASarbanes Oxley会浮现在脑海中)?

于 2008-09-26T19:09:46.893 回答
4

获得一本关于数据建模的非常好的书 - 由真正的数据库开发人员编写,而不是试图教您如何在“现实世界”中完成它的 .NET 开发人员。

数据库设计的问题空间太大了,无法在这样的论坛中进行详细介绍。尽管如此,我还是给你一些个人建议:

听听上面关于规范化的帖子。永远不要非规范化,因为您认为出于性能原因必须这样做。只有在遇到实际性能问题(理想情况下是在您的 QA 环境中,而不是在生产环境中)之后,您才应该进行非规范化。即便如此,请考虑可能有更好的方法来编写查询或首先改进索引。

尽可能地约束数据。列应尽可能为 NOT NULL。在任何应该使用的地方使用 CHECK 约束和 FOREIGN KEY。如果您不这样做,不良数据进入您的数据库并导致很多麻烦和特殊情况编程。

在您真正开始设计表格之前仔细考虑您的数据。很好地了解您的流程将如何流动以及他们需要跟踪哪些数据。很多时候,你乍一看认为是一个实体,结果却是两个实体。例如,在我正在开发的系统中,之前的设计者创建了一个 Member 表,他们应用程序中的所有信息都是 Member 表的一部分。事实证明,成员可能想要更改其应用程序上的数据,但我们仍然需要跟踪原始应用程序的外观,因此应用程序实际上是它自己的实体,而成员是一个最初可能从应用程序。简而言之,做广泛的数据分析,不要只是开始创建表格。

于 2008-09-26T19:57:52.753 回答
4

既然现在已经有好几篇帖子提倡这个了,我再补充一件事……

不要陷入将 ID 列放在所有表上的陷阱。现代数据库设计理论使用真正的主键有很多很好的理由,它们并不是严格的学术理由。我使用过包含数百个表的数据库,其中许多是数百万行表,有超过 1000 个并发用户并且使用真正的主键并没有“崩溃”。

在所有表上使用 ID 列意味着您必须进行多表连接才能遍历数据库,这会变得很麻烦。它还倾向于促进草率的数据库设计,甚至超出通常会导致重复行的问题。另一个问题是,在处理外部系统时,您现在必须与这些 ID 进行通信。

代理 ID 有一些位置 - 类型代码表和概念表(例如,如果规则没有真实世界的标识符,则系统规则表可以使用 ID)。在任何地方使用它们是一个错误 IMO。

这是一个长期存在的辩论,但这是我对此事的看法,因为它的价值。

于 2008-09-26T20:12:09.053 回答
4

数据是永恒的。处理来来去去。

让关系模型成为现实世界的高保真表示。这比什么都重要。

处理将改变和发展多年。但是您的数据——以及数据模型——不能以同样的速度和同样的灵活性发展。您可以添加处理,但不能神奇地添加信息。您不想删除信息(但您可以忽略它。)

得到正确的模型。图表中的实体和关系对于普通的非技术用户来说应该是合理的。即使是应用程序编程也应该简单、清晰和精确。

如果您在模型上遇到困难,请不要发明大而复杂的查询或(更糟糕的)存储过程来解决问题。程序上的变通办法是一个代价高昂的错误。了解你拥有什么,你想做什么,并应用 YAGNI 原则将事情精简到基本要素。

于 2008-09-27T18:59:20.327 回答
2

我知道这已经说明了,但是规范化,规范化,规范化是关键。如果您觉得出于某种原因需要以非规范化格式存储数据,请不要这样做。这应该通过视图或在单独的报告数据库中处理。我的另一个关键建议是尽可能避免使用 text/ntext 字段。

于 2008-11-14T15:45:34.657 回答
2

“数据库的拇指规则 - 总是失败!”

示例:如果您有一个 Customer 表,其中包含 Mailing Address 和 Shipping address 以及 Billing address 列... 创建一个具有地址类型的单独 CustomerAddress 表

如果您有一个 CancellationDetails 表,其中包含 CancellationReason01、CancellationReason02、CancellationReason03.. 创建一个单独的 CancellationReason 表

于 2009-07-22T13:32:59.523 回答
2

实用。记住你的目标是什么,不要疯狂地创造不必要的复杂性。我有一些偏好:

  • 保持表的数量少
  • 与充满空值的宽表相比,更喜欢窄表。
  • 标准化通常很好
  • 触发器通常非常痛苦

但这些都是达到目的的手段(在很多情况下是矛盾的,需要仔细平衡),主要是让需求驱动设计。您对什么是独立实体、什么是另一个实体的一部分以及什么是猫粮(不是您关心其身份的任何东西)的选择完全取决于您的要求。

于 2010-09-13T20:52:40.547 回答
1

如果您有查询要运行很多,请将它们放入存储过程。他们几乎总是跑得更​​快。

于 2008-09-26T18:45:01.383 回答
1

如果您将按主键以外的字段查找行,请确保对它们进行索引。

于 2008-09-26T18:47:22.080 回答
1

是面向对象的语言吗?因此,请尝试在数据库之前为您的对象建模。这将帮助您专注于模型。

于 2008-09-26T18:56:08.423 回答
1

尽可能多地了解需求。然后设计一个逻辑模式,只有在需求发生变化或迁移到完全不同类型的数据库时才需要更改,比如不使用 SQL 的数据库。然后将您的设计细化并扩展为考虑您的特定 DBMS 产品、您的容量、您的负载和您的速度要求的物理设计。

学习如何规范化,还要学习何时打破规范化规则。

于 2008-09-26T19:08:02.373 回答
1

我强烈赞同标准化是至关重要的,出于性能或其他可维护性原因,需要遵循战术非标准化。但是,如果您希望拥有的不仅仅是几张桌子,我想提出一个关于规范化的警告,随着桌子数量的增加,这将使您的生活变得更加轻松。

需要注意的是使每个表的主键成为单个数字列(适合您的 DB 风格)。在学术规范化中,想法是结合实体(表)的任何属性(列),以便您可以唯一标识正在描述的内容(行)的实例,并且最终可以得到多列复合主键. 因此,每当您将该复合键作为外键迁移到其他表时,您最终都会在引用它的每个表中复制这些多列。如果您只有六张桌子,那可能对您有用。但是当你比这大得多时,它很快就会分崩离析。

因此,不要使用多列复合主键,而是使用顺序数字主键,即使这种方法违背了一些严格的规范化教导。

于 2008-09-26T19:23:11.510 回答
1

确保在模型中编码尽可能多的元数据。只需查看数据模型,就应该可以推断出几乎任何业务规则或概念。

这意味着,请注意选择反映用户现实的名称(但如果它有助于模型,请不要害怕改变他们对现实的看法)。

对数据库中的所有约束进行编码。不要依赖应用层只提供敏感数据。首先确保只有合理的数据可以存在。

不要在模型中聚合数据。尽可能保持模型的原子性。即时聚合或将常规聚合作业运行到聚合表中。

在模式之间选择一个好的分区。一些分区与外键有关,而另一些则通过纯粹的物理分离。

于 2008-10-04T17:22:06.930 回答
0

不要使用大量列作为主键

于 2008-09-26T18:52:06.483 回答
0

请记住,标准化仅与您正在建模的内容相关。也许您正在为您的域中的一组对象建模。也许您正在记录一系列事件,其中数据重复,因为相同的数据碰巧不止一次应用。不要把这两件事混为一谈。

于 2008-09-26T19:14:05.963 回答
0

我同意了解您的数据是好的和规范化的。

我建议的其他方法是将非常大的文本字段保存在单独的表格中。例如,如果您有一份合同,您可能希望将有关合同的大量信息保存在一个表中,但将法律(并且非常大)文档保存在单独的表中。只需将主表中的索引放入法律文件即可。

于 2008-09-26T19:23:04.130 回答
0

我想说要记住的重要一点是结构可能会改变。所以不要把自己设计成一个角落。确保你所做的任何事情都会给你留下一些“空间”,甚至有一天可以将数据迁移到不同的结构中。

于 2008-09-27T18:31:32.530 回答
0

尽可能使主键成为序列生成的数字。

于 2010-09-13T20:57:55.690 回答