设计数据库最简单、最有效的方法是什么?从我的角度来看,应用程序的数据存储设计有两种选择:
- 在编写任何应用程序代码之前,尽可能最好地设计数据库。这为您提供了可以使用基本数据结构的优势。在我看来,这样做的缺点是,作为应用程序细节,您将有很多更改,这些更改会影响整个应用程序开发周期中数据更改的内容/位置/方式。
- 在应用程序实现时设计数据库。当您在编写应用程序时需要一些数据库对象时,您可以与应用程序并行(按时间顺序)开发数据库。正如我所见,优点是对数据库结构的更改较少。缺点是应用程序代码和数据库开发之间的时间和开发工作的分配。
根据您的经验,您认为什么是最有成效和最有效的方法?
除了其他答案...
首先捕获您的概念模型应该定义范围和要求。由此,您可以导出逻辑和物理数据模型。
一旦这大部分是静态的,那么您就有了一个稳定的数据库来构建您的应用程序。这与您的第一个选项相反。
你的第二点将以一团混乱、无法维护的泥球告终。数据模型永远不会被修复:如果你没有预先设计它,你将没有时间在发货前修复它。你会忙着把事情搞砸。
架构的微小更改、合并或拆分表、更改关系等都会发生,但在本地化的“孤岛”中,您的模型 + 基本设计将保持不变。
您将很难找到任何不使用敏捷变体的现代软件部门。相比之下,DBA 陷入了黑暗时代,@RobPaller 的答案仍然很普遍。
修改数据库模式从未像修改代码那样容易,这就是为什么不愿采用敏捷方法进行数据库开发和维护的原因。既然我们拥有以与开发人员类似的方式操作的工具和技术,我们绝对应该这样做。仅仅因为改变模式并不容易,并不意味着你不能也不应该。
我并不是在提倡一种随意的数据库设计方法(见评论),只是一种更接近于敏捷开发团队的方法。如果您是敏捷项目的一部分,那么您将不会对将来可能(或可能不会)发生的工作提出要求,因此需要根据您所知道的进行设计,而不是可能的。
我想这使我对您的选项 2 投了票,我怀疑我可能会发现自己对这个选项感到冷漠!
我有幸设计了几个中等复杂度的数据库,这些数据库都用于企业,具有各种前端,包括 Web、Access 和 C#。
通常,我会提前坐下来制定数据库架构。这对我来说总是最有意义的。但是,没有一个案例是我没有最终做出更改、添加新表或遇到困扰我并且基本上来不及修复的方面。
我不认为解决方法是先编写代码。而且我不认为问题是“业务需求不足”,或者至少不是完全可以解决的问题。用户不知道他们需要什么,我也没有能力让他们更努力地思考、更聪明、更有意识或更好地回答我的问题。或者他们争吵,我被命令以某种方式做某事。
我构建的系统通常位于以前没有人涉足过的新领域。我没有得到组织、资源或工具的支持,无法完成顶级设计专业人士的开发团队所做的工作,他们作为一个团队获得的报酬是我构建东西的十倍两倍的时间。
我擅长我的工作。但是只有我一个人在“不做开发”的环境中做这件事。
尽管如此,我在发现业务规则方面做得越来越好。我知道第三种选择(我从敏捷开发实践会议中学到的):
在您设计数据库之前,以及在编写任何代码之前,请绘制粗略的屏幕来显示应用程序将如何工作。它们必须是手绘的,以防止任何人评论字体、大小或尺寸——你只想要功能。
使用透明胶片和纸片,您可以交换进出,一个人是计算机,两个人是非技术主题专家用户(两个人是为了大声说话)和一个人作为主持人,负责记笔记和画画让用户了解他们的思维过程和困惑。用户“点击”并在方框中拖动和书写,“计算机”更新屏幕,每个人都可以体验设计。您将学到在开发过程中之前无法学到的东西。
也许我自相矛盾——也许这是更好的需求发现。但想法是先设计应用程序,而不编写任何代码。我已经开始小规模地做这件事了,而且很有效!尽管我的环境存在问题,但它帮助我从一开始就将数据库设计得更好。我了解到一列必须移动到新的父表中,因为有多种类型。我了解到工作清单必须具有并非来自集成订单系统的常规订单。我什么都学!
在我看来,这是一个巨大的胜利。
您的逻辑数据模型应该有效地捕获应用程序的业务需求。您的物理数据库设计应基于逻辑数据模型,并结合您作为 DBA 认为需要进行的必要更改,以最大限度地提高 RDBMS 的效率。
如果您发现必须在应用程序的软件开发生命周期中对底层数据库设计进行大量更改,则表明两件事:
话虽如此,一旦应用程序投入生产,必须返回并对数据模型进行迭代更改以支持应用程序或底层业务流程的自然演变并不少见。
希望这可以帮助。
对于大多数目的,我会选择选项 2:与其他组件并行构建数据库。尽可能采用迭代方法并在构建每个部分时提供端到端功能。
这确实需要一定的项目纪律。每次更改数据库时都严格应用规范化(Boyce-Codd / 第五范式),以便保持质量并且不会以临时和不一致的模型告终。尽可能积极地处理业务规则和随之而来的数据库约束。如果有疑问,最好尽早实施约束——你总是可以在以后把它拿出来。对实现架构组件的顺序要明智,以最大限度地减少技术债务。拥有一套良好的数据库设计指南,所有开发团队都接受。
当然,所有这些都需要与其他良好的开发工程实践齐头并进:持续集成、测试自动化以及从数据库的角度至关重要的是创建测试数据。真实大小的数据的测试数据创建应该在每次迭代中完成。
在建筑界,“形式追随功能”这句话被创造出来,后来在建造高层建筑时得到了沿用。数据库基础设施和应用程序开发也应如此。
想象一下编写一个应用程序,即时决定你需要一个桌子和一个桌子。当你的应用程序完成后,你有大量的表被视为数组。并排查看所有表格,这些表格肯定会显得没有韵律或理由。
不幸的是,一些开发人员商店会选择 memcached 之类的东西,将数据加载到 RAM 中(因此将其视为数据管道),并拥有像 MySQL 或 PostgreSQL 这样的数据库,其行为仅作为数据存储单元。
使用数据库的动机应该是正确看待它:作为 RDBMS。是的,一个关系数据库管理系统。当您使用 RDBMS 时,您的目标不仅应该是建立用于存储的表,还应该是用于检索的表。表之间的关系应该根据您想要查看的数据及其呈现方式建模。这应该基于数据的内聚性和完整性以及已知的业务规则。这些业务规则可以编码在您的应用程序(Perl、Python、Ruby、Java 等)或数据库中。
结论
我绝对会选择选项 1。它需要适当的计划、数据建模和持续的数据分析。然而,从长远来看,这应该可以最大限度地减少数据库更改。
我牢记以下规则:“您只能从数据库中获取您有数据要生成的信息”。所以,我先设计数据库,然后再设计代码。
为什么?无论我使用什么方法/语言/工具集,如果所有相关数据都经过精心设计并存储在数据库中,我可以检索它。无论是在 C#/Delphi/FORTRAN/COBOL/Assembly/VBA 还是 Crystal Reports 中;OO 设计或事件/数据/任何驱动;敏捷或瀑布。如果数据在那里,如果我使用的工具可以连接到数据库,我可以检索它。如果我可以选择季度收入的订单,我就可以创建销售报告——即使我必须在组装时逐字节编写它。
如果相关数据不存在,或者即使存在但(非)结构化的方式我无法检索我需要的信息 - 如何对其进行编码?
我认为应该在应用程序的任何实际代码之前完成,而不是在设计应用程序之前完成。
如果单独工作,我的典型工作流程是:
由于我经常作为团队的一员工作,而且我们在地理上分散(并且跨时区),我们往往会举行一次初步的启动会议:
然后,我们回到家,编写我们的部分,如果一个组件需要它自己的本地存储,只要该部分的维护者保持其模块的 API 一致。主要的数据存储是作为一个模块处理的,有自己的 API,预计人们会对其进行写入。(在 DB 速度很关键的情况下,API 是表定义,如果进行了更改,我们使用视图或其他机制来呈现旧版本,直到所有模块都可以更新)
通常,这取决于 ;)
例如,假设我们有一个用 Python 开发并使用平面文件的小型工作原型,并且用户对原型的特性很满意,那么我们需要做的就是将其生产化,使用 RDBMS 作为其后端. 在这种情况下,期望第一次做对是合理的——问题很小且定义明确。在这种情况下,预先设计是可行的。
另一方面,当我们在敏捷环境中发现需求时,我们需要一些迭代来更好地理解它们。在这种情况下,数据库与应用程序的其余部分一起发展。这是我们通常做的。因为我们可以重构实时 OLTP 表而无需任何停机时间且风险低,因此我们对数据库重构的可能性感到满意。