设计数据库时要记住的重要事项是什么?

时间:2020-03-06 14:47:55  来源:igfitidea点击:

设计数据库时要记住的重要事项是什么?

我不想将答案局限于我的需求,因为我相信其他人也可以从见解中受益。但是我正在为多客户端社区驱动的站点计划一个内容管理系统。

解决方案

(假设OLTP)

数据结构的规范化。 (性能非规范化通常可以在以后需要的地方进行)

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

"归一化直到痛苦;反归一化直到起作用。"

尝试想象我们将对其执行的SQL查询。

这很重要,因为我们会做很多!

如果我们有要运行很多的查询,请将它们放入存储过程中。它们几乎总是会运行得更快。

如果要按除主键之外的其他字段向上查找行,请确保对其进行索引。

确保使用约束(" CHECK"," NOT NULL"," FOREIGN KEY"," PRIMARY KEY"和" DEFAULT")来确保首先仅将正确的数据存储在数据库中。我们始终可以购买速度更快的硬件,但无法购买更多正确的数据。

不要将大量的列用作主键

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

尽可能多地了解需求。然后设计一个逻辑架构,该逻辑架构仅在需求发生变化或者迁移到完全不同类型的数据库(例如不使用SQL的数据库)时才需要更改。然后,根据特定DBMS产品,体积,负载和速度要求,将设计完善并扩展为一个物理设计。

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

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

是的,考虑一下我们将需要运行的查询和报告的种类。考虑可扩展性。似乎我们在订单表中不需要多于10个产品列,但在需要11时会发生什么。最好有一个订单表和一个订单明细表。

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

设计时要考虑的最关键的事情是首先如何确保数据完整性(如果数据无意义,则数据库无用),其次是如何确保性能。除非我们希望性能不佳,否则不要使用对象模型来设计关系数据库。

接下来最重要的是数据保护和安全性。用户永远不能直接访问数据库表。如果设计需要动态SQL,则他们将必须具有该访问权限。从通过SQL注入攻击之类的潜在黑客的角度来看,这是很糟糕的,但是更重要的是,它为内部人员实施欺诈打开了数据库。是否有需要加密数据的字段
(信用卡信息,密码和社会安全号码是绝对不能未经加密存储的项目)。我们打算如何做以及如何计划审核解密,以确保人们在不需要查看数据时不会解密。我们是否必须经历法律障碍(HIPPA和萨班斯·奥克斯利(Sarbanes Oxley)让人联想到)?

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

并且不要缩写任何东西,除非它非常普遍。不要将数据库变成车牌消息猜测游戏。令人惊奇的是一年后变得不那么明显。

请记住,归一化仅与我们要建模的内容有关。也许我们正在对域中的对象集合进行建模。也许我们正在记录一系列事件,在这些事件中重复数据,因为同一数据碰巧会多次应用。不要混淆两件事。

我同意了解数据是很好并且可以正常化的。

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

我强烈回应标准化是至关重要的,出于性能或者其他可维护性的原因,必须遵循战术非标准化。但是,如果我们希望拥有的表不止几个,那么我想提供一个有关规范化的警告,随着表数量的增加,这将使生活变得更加轻松。

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

因此,即使使用了连续数字主键,也要使用多列复合主键,即使该方法与某些严格的规范化教学相抵触。

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

数据库设计的问题空间实在太大了,以至于无法在这样的论坛中充分讨论。尽管如此,我还是给你一些个人的建议:

听以上关于规范化的文章。永远不要非正规化,因为出于性能原因,我们必须考虑这一点。只有在遇到实际的性能问题(理想情况下是在质量检查环境中,而不是生产环境)后,才应取消规范化。即使这样,也应考虑可能有一种更好的方式来编写查询或者首先改善索引。

尽可能限制数据。列应尽可能不为NULL。无论在何处都应使用CHECK约束和FOREIGN KEY。如果我们不这样做,错误的数据将进入数据库,并引起很多麻烦和特殊情况的编程。

在实际开始设计表之前,请仔细考虑数据。很好地了解流程将如何流动以及需要跟踪哪些数据。通常,我们乍一看是一个实体,结果往往是两个实体。例如,在我正在使用的系统中,以前的设计者创建了一个Member表,而来自其应用程序的所有信息都是Member表的一部分。事实证明,成员可能想要更改其应用程序上的数据,但是我们仍然需要跟踪原始应用程序的外观,因此该应用程序实际上是其自己的实体,并且该成员是一个最初可能从中填充的实体应用程序。简而言之,请进行广泛的数据分析,而不仅仅是开始创建表。

由于现在有几篇文章提倡这样做,因此我将再添加一件事...

不要陷入将ID列放在所有表上的陷阱。现代数据库设计理论使用真正的主键有很多非常好的理由,而这并不是严格的学术原因。我使用的数据库包括数百个表,其中许多是数百万行的表,具有1000多个并发用户,使用真正的主键不会"崩溃"。

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

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

这是一个长期的辩论,但这是我对这个问题的看法,这是值得的。

我要说的一件重要的事情是,结构可能会发生变化。因此,不要将自己设计在角落。确保我们所做的一切都为我们留出了一些"空间",甚至有一天可以将数据迁移到其他结构中。

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

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

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

正确选择模型。图表中的实体和关系对不熟练的非技术用户应具有合理的意义。甚至应用程序编程也应该简单,清晰和精确。

如果我们在模型上苦苦挣扎,请不要发明大型,复杂的查询或者(更糟糕的)存储过程来解决问题。程序性变通方法是一个代价高昂的错误。了解我们拥有的东西,想要做的事情,并应用YAGNI原理将事情简化为基本要素。

确保在模型中编码尽可能多的元数据。仅查看数据模型就应该可以推断出几乎所有业务规则或者概念。

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

对我们可以在数据库中的所有约束进行编码。不要依靠应用程序层仅提供明智的数据。首先确保只有明智的数据才能存在。

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

在模式之间选择合适的分区。某些分区与外键有关,而某些分区则与纯物理分隔有关。

我知道已经说过了,但是规范化,规范化,规范化才是关键。如果存在因某种原因而需要以非规范化格式存储数据的情况,请不要这样做。这应该通过视图或者在单独的报告数据库中进行处理。我的其他主要建议是尽可能避免使用text / ntext字段。

"数据库宕机的经验法则总是不胜枚举!"

例子:
如果我们有一个客户表,其中的邮件地址和收货地址以及账单地址列...创建一个单独的客户地址表,其地址类型为

如果我们有一个带有CancellationReason01,CancellationReason02,CancellationReason03. 的CancellationDetails表,请创建一个单独的CancellationReason表

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

  • 保持表格数量少
  • 较之于充满空值的宽表,它们更喜欢窄表。
  • 规范化通常很好
  • 触发器通常非常痛苦

但这是达到目的的一种方法(并且在许多情况下是矛盾的,需要仔细的平衡),主要是让需求驱动设计。我们对什么是独立实体,什么是另一实体的一部分以及什么是猫食(不是我们关心的身份的任何选择)的选择完全取决于要求。

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