@xuemingdeng
2021-10-16T11:03:08.000000Z
字数 2875
阅读 315
作者丨Justin Etheredge
译者丨屠灵
策划丨闫园园
“关系型数据库,另一个时代的老古董。Codd(关系型数据库之父)在那个时代是伟大的,但软件工程师们不能停留在过去,他们需要不断前进”。
或许你在某些时候听到了类似这样的话。关系型数据库很伟大,但它们就像恐龙一样,正逐渐被非关系型数据库所取代,因为它们无法满足现代企业的需求。
换句话说,它们不能伸缩,不够敏捷。
这类说法有一些是对的,不过也要看情况。
一项比其他任何一种软件经历了更多性能演进的技术,怎么会如此轻易被市场新进者超越了呢?
Rich Hickey(Clojure之父)曾经说过:
“程序员知道什么是好东西,但看不到其中的权衡”。
一些NoSQL数据库的基准测试很惊艳,让我们不得不感叹:它们比关系型数据库快太多、好太多、具有更好的伸缩性。但我们并没有问自己为什么会这样。
我们要问的不应该是“为什么它们会好这么多”,而是“它们放弃掉了哪些东西”。
关系型数据库不是恐龙,不是注定要灭绝的笨重的史前遗骸,它们是鲨鱼。顶级的掠食者经历了数百万年的进化,变成了一种可以完美适应环境的生物。它们的存在是有原因的,而且它们在这个领域的霸主地位不容置疑。
大部分数据库都为我们提供了四种保证:
原子性(Atomicity)——保证同一个事务内的所有操作被当成一个单位,要么都成功,要么都失败,不会出现无效的状态。
一致性(Consistency)——保证每一个操作都不会出现无效的状态。
隔离性(Isolation)——保证数据库的状态在并行执行操作一些操作时就像在串行执行这些操作一样。通常来说,就是一个事务看不到其他事务正在做的修改。
持久性(Durability)——保证事务在提交之后就保持这样的状态,不管是遇到了系统崩溃还是停电。
除了ACID保证,关系型数据库还提供了一系列与数据完整性相关的特性。外键、唯一性约束、非空约束、检测约束,将这些特性与事务结合在一起,可以让你的数据具备逻辑性保证。
所有这些保证结合在一起,让开发一个可靠的、具有数据一致性的系统变得像家常便饭一样。当然,困难的地方在于如何以及何时使用这些保证,但不管怎样,只要用对了,要保持数据一致性就变成了一项简单的任务。
为了突出某些方面的能力,NoSQL数据库通常会在这些保证性当中做出权衡。
有一个叫作BASE的名词被创造出来,用来描述大多数NoSQL数据库在保证性方面所做出的权衡。
基本可用性(Basically Available)——系统可以保证可用性,但可能会牺牲一致性。
软状态(Soft State)——数据库不强制数据一致性。因为是最终一致性的,所以数据有可能被无感知修改。
最终一致性(Eventual Consistency)——不保证数据被修改之后马上对所有数据库消费者可见。通常,这些被修改的数据需要被复制到数据库的其他节点上,任何发生在这段时间内的读操作都可能出现不一致。
与大多数关系型数据库相比,NoSQL数据库提供了不一样的性能特点。接下来,我们来看一下NoSQL数据库在这方面的一些优势,以及它们为了达到这些目的都做了哪些权衡。
高写入性能——很多NoSQL数据库宣称自己具有不可思议的写入性能。关系型数据库花了很多年时间在优化写入性能上,但一直因持久性和一致性保证而受限。关系型数据库的写入速度取决于持久化内存以及它们处理事务、索引和外键(特别如果要阻塞时)的速度。如果可以不保证持久性、不使用事务和外键等,就可以立刻大幅提升写入性能。
高读取性能——很多NoSQL数据库具有不可思议的读取性能。它们将读操作分散到集群的不同实例上,获得高读取性能,却牺牲了一致性。很多NoSQL数据库为了提升读取性能,采用了更为简单的查询语法,不支持复杂的连接、“跨表”查询或分组机制。
水平分片——水平分片是关系型数据库的一大痛点。主要是因为如果将数据分片到多个实例上,就需要牺牲关系型数据库的一致性保证。例如,假设两个表之间有外键关系,并且它们分散在不同的实例上,为了使用外键,你需要扫描集群里的每一个实例,以便找到关联的数据。如果没有数据一致性方面的约束,你就可以将数据分片到大量不同的实例上,就不会遭遇严重的性能瓶颈。
模式变更——很多NoSQL数据库是“无模式(schemaless)”的,所以修改起来更容易。这意味着不管你将什么样结构的数据放入数据库,都会按照原来的样子储存。如果你要增加一个新字段,直接将加了新字段的数据存到数据库。如果要让旧数据也有新字段,只要写一个作业把新字段添加到旧数据中。相比之下,关系型数据库通常有严格的模式限制,需要更复杂的操作来更新模式,特别是在数据库负载很重的情况下。
更可靠和可预测性的性能——NoSQL数据库通常具有更可靠和可预测的性能。大多数关系型数据库在某些情况下会出现性能降级,通常是糟糕的查询导致的。SQL是一种非常强大的语言,但想要弄清楚它的陷阱以及数据库性能会在什么样的情况下受影响是很难的。一些很小的SQL改动都有可能让性能提升一个数量级。很多NoSQL数据库简化了数据访问(有时候只允许基于主键查询),通过复制数据的方式让查询变得更容易,或者将数据导到专门的报表数据库中。
NoSQL数据库的可伸缩性是以牺牲其他方面的保证性为代价。在做出这些权衡时,实际上是将数据库的复杂性转嫁到了应用层。关系完整性和数据一致性问题容易被软件工程师低估。在应用层维护数据一致性或许很容易,但一些边缘情况和失败情况才是你麻烦的来源。
我们经常说,应用程序可以重写,但数据是永恒的。保持数据一致性、干净、具有良好的结构,这是一项艰巨的任务。尽你所能让这项任务变容易,在这方面的投入是值得的。
不过,有时候你可能需要处理海量数据,或者关系型数据库不能很好地满足你的事务性系统。在这些情况下,你需要考虑将部分或者所有数据迁移到NoSQL数据库中。你要看到其中的权衡,而不是只盯着数据库的优点看。你要知道,关系型数据库是鲨鱼。它们经过长期的演化,在存储海量数据方面方面做得非常出色,并承载了大量维护数据完整性和一致性方面的复杂工作。它们会继续演进,并具备NoSQL数据库那样的负载能力(可以看看Postgres的JSONB数据类型https://www.postgresql.org/docs/9.5/functions-json.html)。
如果你以后听到有人说关系型数据库是过时的技术,或者说关系型数据库无法满足他们的MVP(最小可行产品)需求,你就问他们有仔细思想过它们所做出的权衡吗?你要让他们明白,他们以为自己是在越过恐龙的尸体,实际上是错过了人们数十年的努力,这些努力让关系型数据库成为数据库行业的鲨鱼。
原文链接:https://www.simplethread.com/relational-databases-arent-dinosaurs-theyre-sharks/