每个开发者应该知道什么数据库?
无论我们是否喜欢,如果不是我们大多数开发人员,或者不是经常使用数据库,或者有一天可能需要使用数据库。 考虑到野外滥用和滥用的数量,以及每天出现的数据库相关问题的数量,公平地说,开发人员应该知道某些概念 – 即使他们不devise或使用数据库今天。 所以:
开发人员和其他软件专业人员应该了解的关于数据库的重要概念是什么?
回应指引:
保持你的名单短。
每个答案的一个概念是最好的。
具体 。
“数据build模”可能是一项重要技能 ,但究竟意味着什么呢?
解释你的理由。
为什么你的概念很重要? 不要只说“使用索引”。 不要陷入“最佳实践”。 说服你的听众去了解更多。
Upvote的答案你同意。
先阅读其他人的答案。 一个高排名的答案是比两个低排名的答案更有效的说法。 如果您有更多要添加,请添加评论或引用原件。
不要因为它不适用于你个人而降低某些东西。
我们都在不同的领域工作。 这里的目标是为数据库新手提供方向,以获得对数据库devise和数据库驱动开发的充分理解和全面的理解,而不是争夺最重要的头衔。
开发人员应该知道的第一件事情是数据库是什么 ? 不是它们是如何工作的,也不是如何构build它们,甚至不是如何编写代码来检索或更新数据库中的数据。 但是他们是干什么用的?
不幸的是,这个答案是一个移动的目标。 在数据库的嘿嘿,从20世纪70年代到90年代初,数据库是为了共享数据。 如果你使用的是数据库,并且你没有共享数据,那么你要么参与了一个学术项目,要么就是在浪费资源,包括你自己。 build立数据库和驯服数据库pipe理系统是非常重要的任务,就数据被多次利用而言,投资回报必须巨大。
在过去的15年中,数据库已经被用来存储与一个应用程序相关的持久数据。 为MySQL , Access或SQL Server构build数据库已变得如此常规,数据库几乎已成为普通应用程序的常规部分。 有时候,由于数据的实际价值变得明显,任务最初的有限任务被任务蠕变推高。 不幸的是,devise时考虑到单一目的的数据库在开始被推到一个企业范围和关键任务的angular色中时往往会大大失败。
开发人员需要了解的第二件事是数据库是整个数据中心的世界观。 以数据为中心的世界观比以过程为中心的世界观更加不同于大多数开发人员所学的知识。 与这个差距相比,结构化编程和面向对象编程之间的差距相对较小。
至less在概述中,开发人员需要学习的第三件事是数据build模,包括概念数据build模,逻辑数据build模和物理数据build模。
从数据为中心的angular度来看, 概念数据build模确实是需求分析。
逻辑数据build模通常是将特定数据模型应用于概念数据build模中发现的需求。 关系模型的使用远远超过其他任何特定的模型,开发人员需要学习关系模型。 为非平凡的需求devise一个function强大且相关的关系模型并不是一件小事。 如果误解了关系模型,则无法构build好的SQL表。
物理数据build模通常是特定于DBMS的,不需要进行更详细的学习,除非开发人员也是数据库构build者或DBA。 开发人员需要了解的是,物理数据库devise与逻辑数据库devise的分离程度,以及通过调整物理devise来实现高速数据库的程度。
开发人员需要学习的下一件事是速度(性能)是重要的,其他的devise优良性措施更为重要 ,比如能够修改和扩展数据库的范围,或简化编程。
最后,任何与数据库混淆的人都需要明白数据的价值经常超越捕获数据的系统 。
呼!
好问题。 以下是一些没有特定顺序的想法:
-
规范化,至less是第二种正常forms,是至关重要的。
-
通过适当的级联删除和更新考虑,引用完整性也是必不可less的。
-
正确使用检查约束。 让数据库做尽可能多的工作。
-
不要在数据库和中间层代码中分散业务逻辑。 select一个或另一个,最好在中间层代码。
-
确定主键和集群键的一致方法。
-
不要超过索引。 明智地select你的指标。
-
一致的表和列命名。 select一个标准,坚持下去。
-
限制数据库中将接受空值的列数。
-
不要被触发带走。 他们有他们的使用,但可以使事情匆忙复杂化。
-
小心使用UDF。 他们是好的,但是当你不知道他们在查询中被调用的频率可能会导致性能问题。
-
获取Celko关于数据库devise的书。 这个人傲慢但知道他的东西。
首先,开发人员需要了解有关数据库的信息。 他们不仅仅是把SQL放入结果集的魔法设备,而是非常复杂的软件,它们有自己的逻辑和怪癖。
其次,针对不同的目的有不同的数据库设置。 如果有可用的数据仓库,则不希望开发人员将历史报表从联机事务数据库中删除。
第三,开发人员需要了解基本的SQL,包括连接。
过去这取决于开发人员的参与程度。 我曾经从事过开发人员和事实上的DBA工作,那里的数据库pipe理员只是走在过道上,DBA在他们自己的领域。 (我不喜欢第三个)。假设开发人员参与数据库devise:
他们需要了解基本的正常化,至less是前三种正常的forms。 除此之外,得到一个DBA。 对于那些有美国法庭经验的人(和随机电视节目在这里计数),有一个助记符“依靠钥匙,整个钥匙,只有钥匙,所以帮助你Codd。
他们需要掌握一些关于索引的线索,我的意思是他们应该知道索引需要什么,以及它们如何影响性能。 这意味着没有无用的索引,但不害怕添加它们来协助查询。 任何进一步(如天平)应该留给DBA。
他们需要了解数据完整性的需求,并能够指出他们正在validation数据的位置以及在发现问题时所做的工作。 这不一定要在数据库中(在这里很难为用户发出一个有意义的错误信息),但必须在某个地方。
他们应该具备如何获得计划的基本知识,以及如何阅读(至less足以说明algorithm是否有效)。
他们应该隐约地知道触发器是什么,一种观点是什么,可以划分数据库。 他们不需要任何细节,但他们需要知道向DBA询问这些事情。
他们当然不应该干涉生产数据或生产代码或类似的东西,他们应该知道所有的源代码都进入了VCS。
我无疑忘记了一些事情,但是普通的开发人员不一定是DBA,只要有一个真正的DBA在手。
基本索引
我总是很震惊地看到一个没有索引的表或整个数据库,或任意/无用的索引。 即使你没有devise数据库,只需要编写一些查询,至less理解它仍然是至关重要的:
- 什么是你的数据库中索引,什么不是:
- 扫描types之间的差异,如何select它们以及如何编写查询可以影响select;
- 覆盖的概念(为什么你不应该只写
SELECT *
); - 聚集索引和非聚集索引之间的区别
- 为什么更多/更大的指数不一定更好;
- 为什么你应该尽量避免在函数中包装filter列。
devise师还应该了解常见的索引反模式,例如:
- 访问反模式(索引每一列,一个接一个)
- Catch-All反模式(全部或大多数列上的一个大规模索引,显然是在错误的印象中产生的,这会加速涉及任何列的每个可能的查询)。
数据库索引的质量 – 以及您是否利用它来编写查询 – 至今都是最重要的性能指标。 在SO和其他论坛上发表的抱怨performance不佳的10个问题中,有9个总是归结为索引不佳或者不可靠的expression。
正常化
它总是让我觉得有人正在努力写一个过于复杂的查询,而这个查询在标准化devise(“显示我每个区域的总销售额”)方面是完全直截了当的。
如果你一开始就明白这一点,并相应地进行devise,那么以后你将会为自己节省很多痛苦。 归一化后,performance非常容易; 对从一开始就没有devise的数据库进行规范化并不容易。
至less,你应该知道3NF是什么以及如何到达那里。 对于大多数事务性数据库来说,这使得查询容易编写和保持良好的性能是非常好的平衡。
索引如何工作
这可能不是最重要的,但肯定是最被低估的话题。
索引编制的问题在于,SQL教程通常根本没有提及它们,所有玩具的例子都没有任何索引。
即使是更有经验的开发人员也可以编写相当好的(和复杂的)SQL,而不用了解更多的索引而不是“ 索引快速查询 ”。
这是因为SQL数据库在黑盒子方面做得非常好 :
告诉我你需要什么(给我SQL),我会照顾它。
而这完美的作品来检索正确的结果。 SQL的作者并不需要知道系统在幕后做了什么 – 直到一切都变得如此stream利。
这是索引成为一个话题。 但那通常是很晚的,有人(有些公司?)已经在遭遇真正的问题了。
这就是为什么我认为索引是使用数据库时不要忘记的第一个话题 。 不幸的是,忘记它很容易。
放弃
这些论据是从我的免费电子书“ 使用索引,卢克 ”的序言中借鉴的。 我花了很多时间解释索引是如何工作的以及如何正确使用索引。
我只想指出一个观察 – 就是说,大多数回应似乎认为数据库与关系数据库是可以互换的。 还有对象数据库,平面文件数据库。 评估手头软件项目的需求非常重要。 从程序员的angular度来看,数据库的决定可以推迟到晚些时候。 另一方面,数据build模可以在早期实现并取得成功。
我认为数据build模是一个关键的组成部分,是一个相对较旧的概念,但它却被软件行业的许多人所遗忘。 数据build模,特别是概念build模,可以揭示系统的function行为,可以作为发展的路线图。
另一方面,所需的数据库types可以根据许多不同的因素来确定,包括环境,用户量以及可用的本地硬件(如硬盘空间)。
避免SQL 注入以及如何保护您的数据库
每个开发人员都应该知道这是错误的:“剖析数据库操作与剖析代码完全不同。”
传统意义上有一个明确的Big-O。 当你做一个解释EXPLAIN PLAN
(或相当于)你看到的algorithm。 一些algorithm涉及嵌套循环,并且是O ( n ^ 2)。 其他algorithm涉及B树查找并且是O ( n log n )。
这是非常非常严肃的 理解为什么索引很重要是至关重要的。 理解速度 – 规范化 – 非规范化的权衡是至关重要的。 了解为什么数据仓库使用未针对事务更新进行标准化的星型模式是至关重要的。
如果您不清楚正在使用的algorithm,请执行以下操作。 停止。 解释查询执行计划。 相应地调整索引。
另外,推论:更多的索引是不好的。
有时一个关注一个操作的索引会减慢其他操作的速度。 根据这两个操作的比例,添加一个索引可能会有很好的效果,没有整体影响,或者对整体性能不利。
我想每个开发者都应该明白数据库需要不同的范例 。
在编写查询来获取数据时,需要基于集合的方法。 有许多有意思的背景的人为此而斗争。 然而,当他们拥抱它时,即使这个解决scheme可能不是在他们反复关注的思想中首先出现的解决scheme,他们也可以取得更好的结果。
进化数据库devise。 http://martinfowler.com/articles/evodb.html
这些敏捷方法使数据库更改stream程可pipe理,可预测和可testing。
开发人员应该知道,在版本控制,持续集成和自动化testing方面重构生产数据库需要多less时间。
演化数据库devise过程具有pipe理方面的内容,例如,在该代码库的所有数据库中,在某个生命周期之后要删除一列。
至less知道,数据库重构的概念和方法存在。 http://www.agiledata.org/essays/databaseRefactoringCatalog.html
分类和过程描述也可以为这些重构实现工具。
从关系数据库的经验来看,每个开发人员都应该知道:
– 不同的数据types :
使用正确的types进行正确的作业将使您的数据库devise更加健壮,查询速度更快,生活更轻松。
– 了解1xM和MxM :
这是关系数据库的面包和黄油。 您需要了解一对多和多对多的关系,然后在适当的时候应用。
– “ 吻 ”原则也适用于数据库 :
简单总是最好的。 如果您已经学习了数据库如何工作,您将避免不必要的复杂性,这将导致维护和速度问题。
– 指数 :
如果你知道他们是什么,这是不够的。 你需要了解何时使用它们,何时不使用它们。
也:
- 布尔代数是你的朋友
- 图片:不要将它们存储在数据库中。 不要问为什么。
- 用SELECTtestingDELETE
我希望每个人(包括DBA和开发人员/devise人员/架构师)更好地了解如何正确build模业务领域,以及如何将业务领域模型映射/翻译为规范化的数据库逻辑模型,优化的物理模型和适当的面向对象的类模型,由于各种原因,每一个模型都是(可以)不同的,并且理解它们是什么时候,为什么以及它们如何(或者应该是)彼此不同。
我会说强大的基本SQL技能。 到目前为止,我看到很多开发人员对数据库有一些了解,但总是要求提供关于如何制定一个相当简单的查询的提示。 查询并不总是那么容易和简单。 查询规范化的数据库时,必须使用多个连接(内部,左侧等)。
很好的问题。 让我们看看,首先没有人应该考虑查询不完全理解联接的数据库。 这就像开车不知道方向盘和刹车在哪里。 您还需要知道数据types以及如何select最好的数据types。
开发人员应该理解的另一件事是在devise数据库时,应该记住三点:
-
数据完整性 – 如果数据不能被依赖,你基本上没有数据 – 这意味着不要求在应用程序中需要的逻辑,因为许多其他的源可能会触及数据库。 约束,外键和有时触发器是数据完整性所必需的。 不要因为不喜欢它们而不愿意使用它们,或者不想被理解。
-
性能 – 对性能不佳的数据库进行重构非常困难,应该从一开始就考虑性能。 有许多方法可以做同样的查询,有些已知几乎总是比较快,所以不用学习和使用这些方法是短视的。 devise查询或数据库结构之前,请阅读关于性能调优的书籍。
-
安全性 – 这些数据是贵公司的生命血液,也经常包含可被盗取的个人信息。 学习保护您的数据免受SQL注入攻击,欺诈和身份盗用。
查询数据库时,很容易得到错误的答案。 确保你完全理解你的数据模型。 请记住,经常会根据您的查询返回的数据做出实际决策。 如果是错误的,则做出错误的业务决策。 你可以杀死一个不好的查询公司,或者放弃一个大客户。 数据有意义,开发者似乎常常忘记这一点。
数据几乎永远不会消失,从数据存储的angular度考虑,而不是如何在今天获得数据。 那个有十万条logging的那个数据库工作得很好,十年来可能不是那么好。 应用程序很less持续数据。 这是devise性能至关重要的一个原因。
您的数据库将很可能需要应用程序不需要看到的字段。 像复制GUID,date插入字段。 等等。您也可能需要存储更改的历史logging,以及谁制作了这些更改的历史logging,并能够从此仓库恢复不良变更。 想想在你来之前,你打算怎么做呢?去问一个网站如何解决你忘记在更新中放置一个where子句并更新整个表的问题。
切勿开发比生产版本更新版本的数据库。 永远不要永远不要直接针对生产数据库进行开发。
如果您没有数据库pipe理员,请确保有人正在进行备份,并知道如何恢复它们并进行了恢复testing。
数据库代码是代码,没有理由不把代码保存在源代码控制中。
我想这里已经介绍了很多技术细节,我不想补充一些。 我想说的一件事是比技术更具社交性,不要因为“DBA知道最好”的陷阱而成为应用程序开发者。
如果您在查询过程中遇到性能问题,也可以对问题进行归属。 做你自己的研究,并推动数据库pipe理员解释发生了什么,以及他们的解决scheme如何解决这个问题。
完成研究后,请提出自己的build议。 也就是说,我试图find一个合作的解决scheme,而不是把数据库问题留给DBA。
关于Walter M.的回答如下:
“编写得非常好!对于当时没有从事数据库工作的人来说,历史的观点是非常好的”。
历史的angular度在某种意义上是绝对至关重要的。 “忘记历史的人注定要重复。” Cfr XML重复了过去的层次性错误,graphics数据库重复了过去的networking错误,面向对象的系统迫使用户使用层次模型,而每个人甚至只有十分之一的大脑应该知道层次模型不适用于通用的模型,真实世界的目的代表,等等等等。
至于这个问题本身:
每个数据库开发人员应该知道“关系”不等于“SQL”。 然后他们就会明白为什么DBMS供应商非常沉重地让他们失望,为什么他们应该告诉那些相同的供应商想出更好的东西(比如真正关系的DBMS)从他们的客户那里赚钱这样糟糕的软件)。
每个数据库开发人员都应该知道关系代数的一切。 那么就不会有一个开发者留下来,他们不得不把这些愚蠢的“我不知道如何去做我的工作,希望别人为我做”这个问题。
简单的尊重。
- 这不只是一个存储库
- 你可能不知道比供应商或数据库pipe理员更好
- 凌晨三点,高级经理向你大喊,你不会支持
把非规范化看作一个可能的天使,而不是魔鬼,并且把NoSQL数据库视为关系数据库的替代品。
另外,即使不devise数据库,我认为实体关系模型也是每个开发人员必须了解的。 它会让你彻底了解你的数据库是什么。
切勿插入错误文字编码的数据。
一旦你的数据库被多种编码污染,你所能做的最好的是应用启发式和体力劳动的某种组合。
对于一个大量使用数据库的中间专业开发人员(每天或几乎每天都要编写/维护查询),我认为期望应该和其他任何领域一样: 你在大学写了一个 。
每个C ++怪胎在大学里都写了一个string类。 每个graphics极客在大学里都写了一个光线追踪器。 每个networking怪胎在大学里都写了互动网站(通常在我们有“网页框架”之前)。 每个硬件书呆子(甚至软件书呆子)都在大学里build立了一个CPU。 每个医生都在大学里解剖了一整个尸体,即使她只是要服用我的血压,告诉我今天胆固醇太高。 为什么数据库会有所不同?
不幸的是,由于某种原因,今天他们确实有所不同。 人们希望.NET程序员知道C中的string是如何工作的 ,但是RDBMS的内部不应该太在意你 。
从阅读这些知识的过程中获得相同水平的理解几乎是不可能的,甚至无法从顶层去理解。 但是,如果从底部开始,理解每一个部分,那么找出数据库的细节就相对容易一些。 即使是很多数据库极客,似乎无法理解,就像何时使用非关系数据库一样。
也许这有点严格,特别是如果你没有在大学学习计算机科学。 我会把它调低一些: 你今天可以从零开始写一个 。 我不在乎你是否知道PostgreSQL查询优化器是如何工作的,但是如果你自己知道写一个足够多的东西,它可能和他们所做的不一样。 而且你知道,写一个基本的文件真的不难。
非唯一索引中列的顺序非常重要。
第一列应该是内容变化最大的列(即基数)。
这是为了帮助SQL Server在运行时如何使用索引创build有用的统计信息。
了解用于编程数据库的工具!
我浪费了很多时间,试图理解为什么我的代码神秘失败。
例如,如果您使用.NET,则需要知道如何正确使用System.Data.SqlClient
命名空间中的对象。 您需要知道如何pipe理您的SqlConnection
对象,以确保它们已打开,closures,并在必要时妥善处理。
您需要知道,当您使用SqlDataReader
,需要将其与SqlConnection
分开closures。 您需要了解如何在适当的情况下保持连接的打开方式,以最大限度地减less对数据库的命中数(因为在计算时间方面它们相对昂贵)。
除了他们使用的语法和概念选项(如连接,触发器和存储过程)之外,对于每个使用数据库的开发人员来说,一件事情是至关重要的:
知道你的引擎将如何执行你正在写的具体的查询。
我认为这是如此重要的原因是简单的生产稳定。 你应该知道你的代码是如何执行的,所以当你等待一个很长的函数完成的时候,你不会停止你的线程中的所有执行,那么为什么你不想知道你的查询将如何影响数据库,程序,甚至服务器?
实际上,这比我的研发团队多打了分号等等。 假设是查询将很快执行,因为它在开发系统上只有表中的几千行。 Even if the production database is the same size, it is more than likely going to be used a lot more, and thus suffer from other constraints like multiple users accessing it at the same time, or something going wrong with another query elsewhere, thus delaying the result of this query.
Even simple things like how joins affect performance of a query are invaluable in production. There are many features of many database engines that make things easier conceptually, but may introduce gotchas in performance if not thought of clearly.
Know your database engine execution process and plan for it.
- Basic SQL skills.
- Indexing.
- Deal with different incarnations of DATE/ TIME/ TIMESTAMP.
- JDBC driver documentation for the platform you are using.
- Deal with binary data types ( CLOB , BLOB , etc.)
For some projects, and Object-Oriented model is better.
For other projects, a Relational model is better.
The impedance mismatch problem, and know the common deficiencies or ORMs.
RDBMS Compatibility
Look if it is needed to run the application in more than one RDBMS. If yes, it might be necessary to:
- avoid RDBMS SQL extensions
- eliminate triggers and store procedures
- follow strict SQL standards
- convert field data types
- change transaction isolation levels
Otherwise, these questions should be treated separately and different versions (or configurations) of the application would be developed.
Don't depend on the order of rows returned by an SQL query.