What should every developer know about databases?
不管我们喜欢与否,我们中的许多开发人员要么经常使用数据库,要么总有一天不得不使用数据库。考虑到野外滥用和滥用的数量,以及每天出现的大量与数据库相关的问题,公平地说,开发人员应该知道某些概念,即使他们现在不设计或使用数据库。所以:
< BR>
对于数据库,开发人员和其他软件专业人员应该了解哪些重要概念?< BR>
回答指南:保持列表简短。
每个答案一个概念是最好的。
具体点。
"数据建模"可能是一项重要的技能,但这究竟意味着什么?
解释你的理由。
为什么你的概念很重要?不要只说"使用索引"。不要陷入"最佳实践"。说服你的读者去了解更多。
赞成的回答。
先读别人的答案。一个高排名的答案比两个低排名的答案更有效。如果还有更多要添加的内容,请添加注释或引用原始内容。
不要因为某件事对你个人不适用而投反对票。
我们都在不同的领域工作。这里的目标是为数据库新手提供方向,让他们对数据库设计和数据库驱动的开发有一个良好的、全面的理解,而不是竞争最重要的标题。
关于数据库,开发人员首先应该知道的是:数据库是用来做什么的?它们不是如何工作的,也不是如何构建,甚至不是如何编写代码来检索或更新数据库中的数据。但它们是干什么用的?
不幸的是,这个问题的答案是一个移动的目标。在数据库的鼎盛时期,从70年代到90年代初,数据库是用来共享数据的。如果你使用的是一个数据库,而你没有共享数据,你要么参与了一个学术项目,要么你在浪费资源,包括你自己。建立一个数据库和驯服一个数据库管理系统是如此巨大的任务,从数据开发的多次来看,回报必须巨大才能与投资相匹配。
在过去的15年中,数据库已经开始用于存储仅与一个应用程序关联的持久数据。为MySQL、Access或SQL Server构建数据库已经变得非常常规,以至于数据库几乎成为普通应用程序的常规部分。有时,由于数据的真实价值变得明显,初始的有限任务会被任务蠕变推高。不幸的是,当数据库开始被推到一个企业范围和关键任务的角色中时,在设计时只考虑一个单一目的的数据库往往会急剧失败。
开发人员需要了解的关于数据库的第二件事是整个以数据为中心的世界视图。以数据为中心的世界视图与以流程为中心的世界视图的区别比大多数开发人员所学到的任何东西都大。相比之下,结构化编程和面向对象编程之间的差距相对较小。
开发人员需要学习的第三件事,至少在概述中是数据建模,包括概念数据建模、逻辑数据建模和物理数据建模。
概念数据建模实际上是从以数据为中心的角度进行需求分析。
逻辑数据建模通常是特定数据模型对概念数据建模中发现的需求的应用。关系模型比任何其他特定的模型都要使用得多,开发人员肯定需要学习关系模型。为非琐碎的需求设计一个强大的相关关系模型并不是一项琐碎的任务。如果误解了关系模型,就不能构建好的SQL表。
物理数据建模通常是特定于DBMS的,不需要详细学习,除非开发人员也是数据库构建者或DBA。开发人员需要了解的是物理数据库设计与逻辑数据库设计的分离程度,以及仅通过调整物理设计就可以实现高速数据库生成的程度。
开发人员接下来需要了解的是,虽然速度(性能)很重要,但设计优良性的其他度量甚至更重要,例如修改和扩展数据库范围的能力,或者编程的简单性。
最后,任何破坏数据库的人都需要明白,数据的价值往往比捕获它的系统要长。
唷!
问得好。以下是一些没有特殊顺序的想法:
归一化,至少是第二范式,是必不可少的。
引用完整性也是必不可少的,需要考虑到适当的级联删除和更新。
正确使用检查约束。让数据库做尽可能多的工作。
不要在数据库和中间层代码中分散业务逻辑。选择一个或另一个,最好是在中间层代码中。
决定对主键和聚集键使用一致的方法。
不要过度索引。明智地选择索引。
一致的表和列命名。选择一个标准并坚持下去。
限制数据库中接受空值的列数。
别被触发装置搞得神魂颠倒。它们有自己的用途,但会使事情很快复杂化。
小心UDF。它们很好,但当您不知道在查询中调用它们的频率时,它们可能会导致性能问题。
获取塞尔科关于数据库设计的书。这个人很傲慢,但知道自己的东西。
首先,开发人员需要了解关于数据库的一些信息。它们不仅是您放入SQL并得到结果集的神奇设备,而且是具有自身逻辑和特性的非常复杂的软件。
第二,为了不同的目的,有不同的数据库设置。如果有可用的数据仓库,您不希望开发人员通过在线事务数据库生成历史报告。
第三,开发人员需要了解基本的SQL,包括连接。
过去,这取决于开发人员的参与程度。我曾在开发人员和事实上的DBA工作过,DBA就在那里,而DBA在他们自己的领域是不在的。(我不喜欢第三个。)假设开发人员参与了数据库设计:
他们需要了解基本的规范化,至少是前三种正常形式。除此之外,还需要一个DBA。对于那些对我们法庭有任何经验的人(随机的电视节目也算在这里),这里有助于记忆的"依赖于钥匙,整个钥匙,除了钥匙什么都没有,所以帮助你密码。"
他们需要有关于索引的线索,我的意思是他们应该知道他们需要什么索引以及它们可能如何影响性能。这意味着没有无用的索引,但不害怕添加它们来帮助查询。任何进一步的(如余额)都应该留给DBA。
他们需要理解对数据完整性的需求,并且能够指出他们在哪里验证数据,以及如果发现问题他们在做什么。这不必在数据库中(在数据库中很难为用户发出有意义的错误消息),但必须在某个地方。
他们应该具备获得计划的基本知识,以及一般情况下如何阅读计划(至少足以判断算法是否有效)。
他们应该模糊地知道触发器是什么,视图是什么,以及可以对数据库进行分区。他们不需要任何细节,但是他们需要知道向DBA询问这些事情。
当然,他们应该知道不要干预生产数据、生产代码或类似的事情,而且他们应该知道所有源代码都会进入VCS。
毫无疑问,我忘记了一些事情,但是一般的开发人员不需要是DBA,只要有一个真正的DBA在手。
基本标引
看到一个没有索引的表或整个数据库,或者任意/无用的索引,我总是感到震惊。即使您没有设计数据库,只需要编写一些查询,至少要了解以下内容仍然很重要:
- 数据库中的索引内容和非索引内容:
- 扫描类型之间的差异、它们的选择方式以及编写查询的方式如何影响该选择;
- 覆盖的概念(为什么你不应该只写
SELECT * ); - 聚集索引和非聚集索引之间的差异;
- 为什么更多/更大的指数未必更好;
- 为什么要避免在函数中包装筛选列。
设计者还应该知道常见的索引反模式,例如:
- 访问反模式(逐列索引)
- catch-all反模式(在所有或大多数列上有一个大索引,显然是在错误的印象中创建的,它会加速涉及这些列的每个可能的查询)。
数据库索引的质量——以及您是否利用了您编写的查询——是目前为止性能中最重要的部分。在SO和其他论坛上发布的10个问题中,有9个抱怨表现不佳,结果总是由于索引不佳或不可分析的表达。
归一化
看到有人在写一个过于复杂的查询,而这个查询对于规范化的设计是完全直接的("显示每个地区的总销售额"),我总是感到沮丧。
如果你从一开始就理解了这一点,并相应地进行设计,那么以后你就会省去很多痛苦。规范化之后,很容易对性能进行非规范化;规范化一个从一开始就不是这样设计的数据库并不容易。
至少,你应该知道什么是3nF以及如何到达那里。对于大多数事务性数据库,这是使查询易于编写和保持良好性能之间的一个很好的平衡。
索引如何工作
这可能不是最重要的,但肯定是最被低估的话题。
索引的问题是,SQL教程通常根本不提到它们,所有的玩具示例都在没有任何索引的情况下工作。
甚至更有经验的开发人员也可以在不了解索引的情况下编写相当好(和复杂)的SQL,而不是"索引使查询速度更快"。
这是因为SQL数据库可以很好地作为黑盒工作:
Tell me what you need (gimme SQL), I'll take care of it.
这对于检索正确的结果非常有效。SQL的作者不需要知道系统在幕后做了什么——直到一切都变得非常缓慢……
这时索引就成了一个主题。但通常都很晚了,有人(某个公司?)已经有了真正的问题。
这就是为什么我认为索引是第一个在使用数据库时不可忘记的主题。不幸的是,很容易忘记它。
免责声明
这些论点是从我的免费电子书"使用索引,卢克"的前言中借用的。我花了很多时间解释索引如何工作以及如何正确使用它们。
我只是想指出一个观察结果,那就是大多数的响应都假定数据库可以与关系数据库互换。还有对象数据库、平面文件数据库。评估手头软件项目的需求是很重要的。从程序员的角度来看,数据库决策可以延迟到稍后。另一方面,数据建模可以在早期实现并取得很大的成功。
我认为数据建模是一个关键的组件,是一个相对古老的概念,但它却被软件行业的许多人遗忘了。数据建模,尤其是概念建模,可以揭示系统的功能行为,可以作为开发的路线图。
另一方面,所需的数据库类型可以根据许多不同的因素来确定,包括环境、用户卷和可用的本地硬件(如硬盘空间)。
避免SQL注入以及如何保护数据库
每个开发人员都应该知道这是错误的:"分析数据库操作与分析代码完全不同。"
传统意义上有一个明显的大O。当您执行
这是非常非常严重的。理解索引为什么重要是很重要的。理解速度归一化-非规范化折衷是至关重要的。理解为什么数据仓库使用的星型模式不是事务更新的标准化模式,这一点很重要。
如果您不清楚所使用的算法,请执行以下操作。停下来。解释查询执行计划。相应地调整索引。
而且,推论是:指数越多越好。
有时,一个集中于一个操作的索引会减慢其他操作的速度。根据这两个操作的比率,添加一个索引可能会有好的效果,没有整体影响,或者对整体性能有害。
好问题。让我们看看,首先,没有人应该考虑查询一个不完全理解联接的数据库。这就像在不知道方向盘和刹车在哪里的情况下驾驶汽车。您还需要知道数据类型以及如何选择最佳数据类型。
开发人员应该理解的另一件事是,在设计数据库时,您应该记住三件事:
数据完整性—如果数据不能被依赖,那么您基本上没有数据—这意味着不要在应用程序中放置所需的逻辑,因为许多其他源可能接触到数据库。约束、外键和有时触发器是数据完整性所必需的。不要因为不喜欢或者不想被打扰去理解它们而不使用它们。
性能-重构性能不佳的数据库非常困难,应该从一开始就考虑性能。做同样的查询有很多种方法,有些方法几乎总是更快,不学习和使用这些方法是短视的。在设计查询或数据库结构之前,请阅读一些关于性能优化的书籍。
安全性-此数据是您公司的生命之血,它还经常包含可能被盗的个人信息。学习如何保护您的数据免受SQL注入攻击、欺诈和身份盗窃。
在查询数据库时,很容易得到错误的答案。确保您完全理解您的数据模型。记住,通常实际决策是基于查询返回的数据做出的。如果是错误的,就会做出错误的业务决策。你可以因为糟糕的查询而毁了一家公司,或者失去一个大客户。数据有意义,开发人员往往会忘记这一点。
数据几乎永远不会消失,想想随着时间的推移存储数据,而不仅仅是如何在今天得到它。这个数据库在拥有10万条记录时运行良好,十年后可能就不那么好了。应用程序很少像数据那样持久。这就是为什么性能设计至关重要的一个原因。
您的数据库可能需要应用程序不需要查看的字段。例如复制的guid、日期插入字段。等。您可能还需要存储更改的历史记录,以及谁在何时进行了更改,并且能够从此仓库中恢复坏的更改。在你来问一个网站如何解决你忘记在更新中放一个WHERE子句并更新整个表的问题之前,想想你打算怎么做。
永远不要在比生产版本更新的数据库版本中开发。从不,从不,从不直接针对生产数据库进行开发。
如果您没有数据库管理员,请确保有人正在进行备份,并且知道如何还原它们,并已测试还原它们。
数据库代码就是代码,没有理由不把它和其他代码一样保存在源代码管理中。
我认为每个开发人员都应该理解数据库需要不同的范例。
在编写查询以获取数据时,需要使用基于集合的方法。许多有着互动背景的人都在为此奋斗。然而,当他们接受它的时候,他们可以取得更好的结果,即使解决方案可能不是首先在他们的迭代集中思想中出现的。
进化数据库设计。http://martinfowler.com/articles/evodb.html网站
这些敏捷的方法使数据库变更过程易于管理、可预测和可测试。
开发人员应该知道,从版本控制、持续集成和自动化测试方面重构生产数据库需要什么。
渐进式数据库设计过程具有管理方面的特点,例如,在该代码库的所有数据库中的某个生命周期结束后,将删除一列。
至少要知道,数据库重构的概念和方法是存在的。http://www.agiledata.org/散文集/databaserefactoringcatalog.html
分类和过程描述也使得为这些重构实现工具成为可能。
关于Walter M回答的以下评论:
"写得很好!历史视角对于当时没有做数据库工作的人(即我)来说是很好的。
从某种意义上说,历史观点是至关重要的。"忘记历史的人注定要重蹈覆辙。CFR XML重复了过去的层次错误,图形数据库重复了过去的网络错误,OO系统强迫用户使用层次模型,而每个只有十分之一大脑的人都应该知道层次模型不适合于现实世界的通用表示,等等。
至于问题本身:
每个数据库开发人员都应该知道"关系"不等于"SQL"。然后,他们就会明白为什么DBMS供应商让他们如此失望,以及如果他们想继续从客户那里为这种糟糕的软件榨取大量的钱,为什么他们应该告诉这些供应商拿出更好的东西(例如,真正相关的DBMS)。
每个数据库开发人员都应该知道关系代数的一切。然后就不再有一个开发人员离开了,他不得不发布关于堆栈溢出的这些愚蠢的问题:"我不知道如何做我的工作,并且希望其他人为我做"。
我想这里已经介绍了很多技术细节,我不想再增加它们。我想说的一件事是,作为一个应用程序开发人员,不要落入"DBA知道最好的"陷阱,而不是技术上的陷阱。
如果您在查询方面有性能问题,那么也要取得问题的所有权。做你自己的研究,让DBA解释发生了什么以及他们的解决方案是如何解决这个问题的。
在你完成研究之后,也要提出你自己的建议。也就是说,我试图找到一个解决问题的合作解决方案,而不是将数据库问题留给DBA。
我希望所有人,包括DBA和开发人员/设计师/架构师,更好地理解如何正确地建模业务域,以及如何将该业务域模型映射/转换为规范化的数据库逻辑模型、优化的物理模型和适当的面向对象的类模型,每个类模型(可以是不同的),以便r各种原因,并理解它们何时、为什么和如何(或应该)彼此不同。
简单的尊重
- 它不仅仅是一个仓库
- 您可能比供应商或DBA更了解
- 你不会在凌晨3点支持它的,高级经理们会冲你大喊大叫
根据我对关系数据库的经验,每个开发人员都应该知道:
-不同的数据类型:
为正确的工作使用正确的类型将使您的数据库设计更加健壮,您的查询更快,您的生活也更轻松。
-了解1XM和MXM:
这是关系数据库的基础。你需要了解一对多和多对多的关系,并在适当的时候加以应用。
-"K.I.S.S."原则也适用于争议裁决委员会:
简单总是最有效的。如果您已经研究了DB的工作方式,您将避免不必要的复杂性,这将导致维护和速度问题。
-指数:
如果你知道它们是什么就不够了。你需要了解何时使用它们,何时不使用。
也:
- 布尔代数是你的朋友
- 图片:不要把它们存储在数据库中。不要问为什么。
- 用select测试删除
我想说的是很强的基本SQL技能。到目前为止,我见过很多开发人员,他们对数据库有一点了解,但总是询问如何制定一个非常简单的查询的技巧。查询并不总是那么容易和简单。查询标准化良好的数据库时,必须使用多个联接(内部联接、左侧联接等)。
切勿使用错误的文本编码插入数据。
一旦您的数据库被多个编码污染,您所能做的最好的就是应用一些启发式和手工劳动的组合。
将非规范化视为一个可能的天使,而不是魔鬼,还将NoSQL数据库视为关系数据库的替代方案。
另外,我认为实体关系模型对于每个开发人员都是必须知道的,即使您不设计数据库。它会让你彻底了解你的数据库是关于什么的。
对于一个经常使用数据库(每天或几乎每天编写/维护查询)的中级专业开发人员来说,我认为他们的期望应该与任何其他领域一样:你在大学里写过一个。
每个C++ GEK都在大学里编写了一个字符串类。每一个图形怪人在大学里都写了一个光线跟踪器。在大学里,每个网络极客都会写互动网站(通常在我们有"网络框架"之前)。每一个硬件书呆子(甚至是软件书呆子)在大学里都建造了一个CPU。在大学里,每个医生都解剖了一整具尸体,即使她只想测量我的血压,告诉我我今天胆固醇太高。为什么数据库会有所不同?
不幸的是,由于某些原因,它们今天看起来确实有所不同。人们希望.NET程序员知道字符串在C中是如何工作的,但是RDBMS的内部不应该太关心您。
仅仅从阅读它们,甚至从最高层一路工作,几乎不可能获得同样程度的理解。但是,如果您从底层开始并理解每一个部分,那么为您的数据库找出具体的细节就相对容易了。即使是很多数据库怪人似乎都不知道的事情,比如何时使用非关系数据库。
也许这有点严格,尤其是如果你在大学里没有学习计算机科学。我会把它调低一些:你今天可以写一篇,完全,从头开始。我不在乎您是否知道PostgreSQL查询优化器的具体工作原理,但是如果您足够了解自己编写一个,那么它可能与它们所做的工作没有太大的不同。你知道,写一本基本的书其实并不难。
除了他们使用的语法和概念选项(如联接、触发器和存储过程)之外,对于每个使用数据库的开发人员来说,一件至关重要的事情是:
了解您的引擎将如何以特定的方式执行您正在编写的查询。
我认为这一点如此重要的原因仅仅是生产的稳定性。您应该知道代码是如何执行的,这样在等待一个长函数完成时就不会停止线程中的所有执行,那么为什么您不想知道查询将如何影响数据库、程序甚至服务器?
这实际上是我的研发团队多次遇到的问题,而不是丢失分号之类的内容。假设查询将很快执行,因为它在开发系统上执行,表中只有几千行。即使生产数据库的大小相同,它也很可能会被更多地使用,从而受到其他约束,例如多个用户同时访问它,或者其他查询出错,从而延迟了此查询的结果。
即使是连接如何影响查询性能这样的简单事情,在生产中也是无价的。许多数据库引擎有许多特性可以使概念上的工作更容易,但如果不清楚地考虑,可能会在性能上引入gotchas。
了解数据库引擎的执行过程并计划执行过程。
非唯一索引中的列顺序很重要。
第一列应该是内容变化性最大的列(即基数)。
这有助于SQL Server在运行时创建如何使用索引的有用统计信息。
- 基本的SQL技能。
- 索引。
- 处理日期/时间/时间戳的不同形式。
- 您正在使用的平台的JDBC驱动程序文档。
- 处理二进制数据类型(CLOB、BLOB等)
了解用于编程数据库的工具!!!!
我浪费了太多时间试图理解为什么我的代码神秘地失败了。
例如,如果您正在使用.NET,您需要知道如何正确地使用
你需要知道,当你使用
Programmers, sit your butt down. I need to have a talk with you. from programming
有三件事是神奇的数字:
您的数据库也需要版本控制。
光标很慢,你可能不需要它们。
触发是邪恶的*
几乎总是
对于某些项目,面向对象模型更好。
对于其他项目,关系模型更好。
RDBMS兼容性
查看是否需要在多个RDBMS中运行应用程序。如果是,可能需要:
- 避免RDBMS SQL扩展
- 消除触发器和存储过程
- 遵循严格的SQL标准
- 转换字段数据类型
- 更改事务隔离级别
否则,这些问题应该单独处理,并开发应用程序的不同版本(或配置)。
阻抗失配问题,并了解常见的缺陷或波形。
不依赖于SQL查询返回的行的顺序。