设计数据库时要记住哪些重要事项?
我不想限制您对我的需求的回答,因为我相信其他人也可以从您的见解中受益。但我正在为多客户社区驱动的网站规划一个内容管理系统。
答案 0 :(得分:38)
“正常化,直到它受伤;去标准化直到它起作用。”
答案 1 :(得分:21)
答案 2 :(得分:15)
预先建立一致的命名标准。从长远来看,它将节省几分钟不必要的思考。 (这可能看起来很讽刺,但我很认真。)
并且不要缩写任何内容,除非非常普通。不要将数据库变成牌照消息猜测游戏。一年之后变得不明显的事情令人惊讶。
答案 3 :(得分:14)
确保您使用约束(CHECK
,NOT NULL
,FOREIGN KEY
,PRIMARY KEY
和DEFAULT
)以确保只有正确的数据存储在数据库首先。您可以随时购买更快的硬件,但无法购买更多正确的数据。
答案 4 :(得分:9)
试着想象一下你将针对它执行的SQL查询。
这很重要,因为你会做很多的事情!
答案 5 :(得分:7)
我会记住一些事情。确保每个表都有一种唯一识别记录的方法(这样可以节省数小时的痛苦)。标准化但不加入大型多列自然键,除非您希望整个过程变慢。请改用父表中自动生成的数字键。
是的,请考虑您需要运行的查询和报告的类型。考虑可扩展性。您可能看起来在订单表中不需要超过10个产品列,但在需要时会发生什么情况11.最好有订单表和订单明细表。
确保将所有数据完整性规则合并到数据库中。并非所有数据都发生在用户界面上,而且我不得不尝试修复太多乱糟糟的数据库,因为设计人员认为将所有规则放在GUI中都可以。
设计时要考虑的最重要的事情首先是如何确保数据完整性(如果数据毫无意义,那么数据库是无用的)以及如何确保性能。除非您想要性能不佳,否则不要使用对象模型来设计关系数据库。
下一个最重要的是数据保护和安全性。用户永远不应该直接访问数据库表。如果您的设计需要动态SQL,则必须具有该访问权限。从SQL注入攻击等潜在黑客攻击的角度来看,这很糟糕,但更重要的是,它会为内部人员欺诈行为打开数据库。是否存在需要加密数据的字段 (信用卡信息,密码和社会安全号码是永远不应加密存储的项目之一)。您打算如何做到这一点?您计划如何审核解密,以确保人们在不需要查看数据时不解密。您是否必须经历合法的箍(HIPPA和Sarbanes Oxley?)
答案 6 :(得分:4)
获得一本关于数据建模的非常好的书 - 一本由真正的数据库开发人员编写,而不是.NET开发人员,他试图教你如何在“现实世界”中完成它。
数据库设计的问题空间太大而无法在像这样的论坛中被大量覆盖。尽管如此,我还是会给你一些个人指示:
听取上面关于规范化的帖子。永远不要反规范,因为你认为你必须出于性能原因。在遇到实际性能问题后(理想情况是在QA环境中,而非生产环境),您应该只进行非规范化。即便如此,请考虑可能有更好的方法来编写查询或首先改进索引。
尽可能地限制数据。列应尽可能不为NULL。在任何地方使用CHECK约束和FOREIGN KEY。如果你不这样做,那么错误的数据将进入你的数据库并引起很多麻烦和特殊情况编程。
在实际开始设计表之前,请仔细考虑您的数据。熟悉流程的流程以及需要跟踪的数据。通常情况下,您认为实体乍一看是两个实体。例如,在我正在使用的系统中,前一个设计器创建了一个Member表,其应用程序中的所有信息都是Member表的一部分。事实证明,成员可能想要更改其应用程序上的数据,但我们仍然需要跟踪原始应用程序的外观,因此应用程序实际上是它自己的实体,而成员是最初可能填充的实体。应用程序。简而言之,进行广泛的数据分析,不要只是开始创建表格。
答案 7 :(得分:4)
由于现在有几个帖子提倡这个,我还要再添加一个......
不要陷入在所有表格上放置ID列的陷阱。现代数据库设计理论使用真正的主键有许多非常好的理由,并且它们不是严格的学术原因。我使用过包含数百个表的数据库,其中许多是数百万个行表,超过1000个并发用户并使用真正的主键没有“分解”。
在所有表上使用ID列意味着您必须执行多表连接才能遍历数据库,这将成为一个很大的麻烦。它还倾向于促进草率的数据库设计,甚至超过这通常会导致重复行的问题。另一个问题是,在处理外部系统时,您现在必须传达这些ID。
代理ID的位置 - 类型代码表和概念表(例如,如果规则没有真实标识符,系统规则表可以使用ID)。到处使用它们是IMO的错误。
这是一场长期的辩论,但这是我对此事的看法,以及它的价值。
答案 8 :(得分:4)
数据是永恒的。加工来了。
让关系模型成为现实世界的高保真表示。这比什么都重要。
处理将改变并发展多年。但是,您的数据 - 以及数据模型 - 无法以相同的速度和相同的灵活性发展。您可以添加处理,但不能神奇地添加信息。您不想删除信息(但可以忽略它。)
获取模型正确。图表中的实体和关系应该对休闲的非技术用户有理性的意义。甚至应用程序编程也应该简单,清晰和准确。
如果您正在努力使用该模型,请不要发明大型复杂查询或(更糟糕的)存储过程来解决问题。程序性解决方案是一个代价高昂的错误。了解您拥有的,想要做的事情,并应用YAGNI原则将事情简化为必需品。
答案 9 :(得分:2)
务实。请记住您的目标是什么,不要发疯创造不必要的复杂性。我有一些偏好:
但这些是达到目的的手段(在许多情况下是矛盾的,需要仔细平衡),主要是让需求驱动设计。您选择什么是单独的实体,什么是另一个实体的一部分,什么是猫粮(不是您关心的任何身份)完全取决于您的要求。
答案 10 :(得分:2)
“数据库的拇指规则 - 向下总是击败!”
实施例: 如果您有一个Customer表,其中包含邮寄地址和送货地址以及开票地址的列...使用地址类型创建单独的CustomerAddress表
如果你有CancellationDetails表和CancellationReason01,CancellationReason02,CancellationReason03 ..创建一个单独的CancellationReason表
答案 11 :(得分:2)
我知道已经说明了这一点,但规范化,规范化,规范化是关键。如果有一个实例,您认为无论出于何种原因需要以非规范化格式存储数据,请不要这样做。这应该通过视图或单独的报告数据库来处理。我的另一个重要建议是尽可能避免使用text / ntext字段。
答案 12 :(得分:1)
如果您要按主键以外的字段查找行,请确保将它们编入索引。
答案 13 :(得分:1)
是面向对象的语言吗?因此,尝试在数据库之前建模对象。这将有助于您专注于模型。
答案 14 :(得分:1)
尽可能多地了解要求。然后设计一个逻辑模式,只需要在需求发生变化时进行更改,或者迁移到完全不同类型的数据库,例如不使用SQL的数据库。然后将您的设计细化并扩展为物理设计,该设计考虑了您的特定DBMS产品,体积,负载和速度要求。
了解如何规范化,还要了解何时打破规范化规则。
答案 15 :(得分:1)
如果您有查询要运行A LOT,请将它们转换为存储过程。他们几乎总是跑得更快。
答案 16 :(得分:1)
我强烈反应归一化至关重要,因为性能或其他可维护性原因会导致战术反规范化。但是,如果您期望只有几张桌子,我想提供一个关于规范化的警告,随着表格数量的增长,这将使您的生活变得更加轻松。
需要注意的是使每个表的主键成为一个数字列(适合您的DB风格)。在学术规范化中,想法是组合实体(表)的任何属性(列),以便您可以唯一地标识所描述内容的实例(行),并且最终可以得到多列复合主键。因此,每当您将该组合键作为外键迁移到其他表时,最终会复制引用它的每个表中的多个列。如果你只有六张桌子,这可能对你有用。但是当你比这更大的时候,它会很快崩溃。
因此,使用顺序数字主键代替多列复合主键,即使这种方法违反了一些严格的规范化教导。
答案 17 :(得分:1)
确保在模型中编码尽可能多的元数据。应该可以通过查看数据模型来推断几乎任何业务规则或概念。
这意味着,要注意挑选反映用户现实的名称(但如果它对模型有帮助,不要害怕改变他们对现实的看法)。
对数据库中的所有约束进行编码。不要依赖应用层来提供合理的数据。确保首先只能存在合理的数据。
不要在模型中进行聚合数据。保持模型尽可能原子。即时聚合或将常规聚合作业运行到聚合表中。
在架构之间选择一个好的分区。一些分区对于外键有意义,有些则通过纯粹的物理分离。
答案 18 :(得分:0)
尽可能使主键成为序列生成的数字。
答案 19 :(得分:0)
我要说的一件重要的事情是,结构可能会发生变化。所以不要把自己设计成一个角落。确保无论你做什么都会留下一些“空间”,甚至可以在某一天将数据迁移到不同的结构中。
答案 20 :(得分:0)
我同意了解您的数据是好的并正常化。
我建议的其他方法是在一个单独的表中保留非常大的文本。例如,如果您有合同,您可能希望在一个表中保留有关合同的大量信息,但将合法(和非常大)的文档保存在单独的表中。只需将主表中的索引放入法律文件中即可。
答案 21 :(得分:0)
请记住,规范化仅与您建模的内容相关。也许您正在为域中的对象集合建模。也许您正在记录一系列事件,其中重复数据,因为同一数据恰好适用于多次。不要混淆这两件事。
答案 22 :(得分:0)
不要使用大量列作为主键