为什么NoSQL比RDBMS更适合“横向扩展”?

83
我在技术博客阅读了有关NoSQL优缺点的文章,以下是原文:
"多年来,为了提高数据库服务器性能,数据库管理员一直不得不购买更大的服务器以应对数据库负载的增加(向上扩展),而不是将数据库分布在多个“主机”上随着负载的增加进行扩展(向外扩展)。RDBMS通常不容易向外扩展,但新型的NoSQL数据库实际上是为了方便地扩展到利用新节点而设计的,并且通常考虑到低成本的普通硬件。"
我对RDBMS和NoSQL的可伸缩性感到困惑。
我的疑问是:
1. 为什么RDBMS不太容易向外扩展?为什么要购买更大的服务器而不是更多便宜的服务器。 2. 为什么NoSQL更容易向外扩展?
7个回答

90

我一直在试图弄清楚NoSQL和RDBMS之间的真正区别,但总是得到不能令我满意的答复。在我的搜索中,实际上只有两个主要差异,其中只有一个是真正的优势。

  1. ACID vs BASE - NoSQL通常会省略SQL的某些ACID功能,通过将此抽象层留给程序员来实现,从而“欺骗”提高性能。这已经由之前的帖子涵盖过了。

  2. 水平扩展 - NoSQL的真正优势在于水平扩展,也称为分片。考虑到NoSQL“文档”是一种“自包含”的对象,“文档”可以位于不同的服务器上,而不必担心从多个服务器连接行,这是关系模型的情况。

假设我们想返回这样一个对象:

post {
    id: 1
    title: 'My post'
    content: 'The content'
    comments: {
      comment: {
        id: 1
      }
      comment: {
        id: 2
      }
      ...

    views: {
      view: {
        user: 1
      }
      view: {
        user: 2
      }
      ...
    }
}
在NoSQL中,该对象基本上将按原样存储,因此可以作为一种自包含对象驻留在单个服务器上,而不需要与其他表中的数据进行连接,这些表可能驻留在其他DB服务器上。
但是,在关系型数据库中,该帖子需要与“comments”表中的评论以及来自“views”表的视图连接。在SQL中,这不是问题,直到数据库被分成片段,在这种情况下,“comment 1”可能在一个DB服务器上,而“comment 2”仍在另一个DB服务器上。这使得在已经水平扩展的RDBMS中创建完全相同的对象比在NoSQL DB中更困难。
有没有任何数据库专家可以证实或反驳这些观点?

3
如果在关系型数据库中有一个单独的表来存储帖子数据,包括评论和浏览量,那该怎么办? - Anand
2
是的,对于连接性能问题,去规范化数据库是一种可行的解决方法,但显然会以任何数据非规范化(冗余、更新成本、大小等)为代价。顺便说一下,这也是面向聚合的NoSQL解决方案(如键值、列式和文档型)的整体思路。 - Ignacio Hagopian
5
如果我们去规范化关系型数据库,能否获得与 NoSQL 相同的性能? - Kartik

65

RDBMS具有ACID(http://en.wikipedia.org/wiki/ACID)并支持事务。由于这些概念,使用RDBMS进行“横向扩展”更难实现。

NoSQL解决方案通常提供记录级原子性,但无法保证一系列操作成功(事务)。

归根结底:为了保持数据完整性并支持事务,多服务器RDBMS需要具有快速的后端通信通道来同步所有可能的事务和写入,同时防止/处理死锁。

这就是为什么通常只会看到1个主服务器(写入者)和多个从服务器(读取者)的原因。


1
RavenDB支持事务,但不是传统意义上的。 - vcsjones
7
如果你需要它,那就不太好了 :( NoSQL和SQL之间是一个权衡,即易于扩展性与易于事务管理之间的权衡。因此,如果你说需要事务并选择SQL,则可扩展性将更加困难;如果你选择NoSQL,然后想要强大的事务支持,生活会变得艰难。 - Tony Hopkinson
2
你可以始终使用混合系统。例如:电子商务。实际会计部分使用关系型数据库管理系统,其余部分使用MongoDB。 - Martin Samson
3
为了保持数据完整性并支持事务,一个多服务器关系型数据库需要具备快速的后端通信渠道来同步所有可能的事务和写操作,同时避免/处理死锁。正是如此,Clustrix数据库通过利用Infiniband作为快速互联方式以及MVCC技术来实现扩展写操作,并且保证ACID特性。这种扩展RDBMS解决方案有时被称为NewSQL。 - clieu
@clieu,我不认为您被允许在堆栈注释中进行广告宣传。除此之外,自数据库问世以来,SQL数据库一直在进行扩展。唯一的区别是,它们旨在由专业人员进行配置和安装,而不是旅游者,这也是noSQL类型服务的目标。 - Morg.
显示剩余2条评论

17

典型的关系型数据库(RDBMs)对数据一致性做出了强有力的保证。这在某种程度上要求节点之间进行每次交易的通信,这限制了其横向扩展的能力,因为节点越多意味着需要更多的通信。

NoSQL系统做出了不同的折衷。例如,它们不能保证第二个会话将立即看到第一个会话提交的数据,从而使存储某些数据的事务与向每个用户提供该数据的过程分离。请搜索“最终一致性”。因此,单个事务不需要等待任何(或少得多的)节点间通信,因此它们能够更轻松地利用大量节点。


4
关系型数据库系统(RDBMS)也可以进行不同的权衡,以实现性能和持久性之间的平衡,但是很少有人知道这一点。参见:http://tqdev.com/2016-trading-durability-for-performance-without-nosql - mevdschee

10
为什么NoSQL数据库比SQL更容易进行水平扩展?我一直在试图弄清楚为什么人们总是这么说。我看过很多文章,但它们只用一些行业不熟悉的术语和模糊的假设把我搞糊涂了。我建议您阅读Martin Kleppman的《设计数据密集型应用程序》。此外,我会分享一些我对这个主题的理解。
联接(JOINS)- 对于多对一或多对多关系,目前发明的任何数据库都无法将数据保持在一个表或文档中,因此,如果数据被分片或分区,无论是SQL还是NoSQL,延迟都会相同,数据库都必须查找两个文档。在一对多关系的情况下,NoSQL似乎是占优势的。例如:
NoSql
学生
{
  "name": "manvendra",
  "education": [
    {
      "id": 1,
      "Degree": "High School"
    },
    {
      "id": 2,
      "Degree": "B.Tech"
    }
  ]
}

教育机构收藏

[
  {
    "id": "1",
    "name": "army public school"
  },
  {
    "id": "2",
    "name": "ABES Engineering College"
  }
]

SQL

学生表

id | name        
1  | Manvendra

教育学院

id | Name
1  | Army public school
2  | ABES Engineering college

研究表格

student  | education institute | degree
1        | 1                   | high school
1        | 2                   | B.tech

假设在NoSql的情况下,如果两个集合的数据存储在不同的节点上,那么解析教育机构的ID将需要额外的时间,而在SQL数据库中情况也是类似的,那么这有什么好处呢?我想不到任何好处。

另外,你可能会想,为什么我们不能将教育机构的信息也存储在同一个学生集合中,像这样:

{
  "name": "manvendra",
  "education": [
    {
      "name": "Army public school",
      "Degree": "High School"
    },
    {
      "name": "ABES Engineering College",
      "Degree": "B.Tech"
    }
  ]
}

这个设计非常不好,因为学生和教育机构之间存在多对多的关系,许多学生可能从同一所学校学习,因此,如果明天该机构的名称或任何信息发生变化,则在所有地方进行更改将是一项非常困难的挑战。然而,在一对多的关系中,我们可以将所有信息合并在一起,例如:考虑客户和订单关系。
{
  "name": "manvendra",
  "order": [
    {
      "item": "kindle",
      "price": "7999"
    },
    {
      "item":"iphone 12",
      "price":"too much"
    }
  ]
}

由于一个订单只属于一个顾客,因此将订单信息存储在一个地方是有意义的,但是存储商品ID或名称是另一种选择。如果我们在这里使用SQL数据库,则会有两个表,即订单和顾客,如果数据未存储在同一节点中,则不会给查询带来良好的结果。

因此,在论述为什么NoSql数据库更容易横向扩展时提到连接操作没有意义。

事务

无论是SQL(Postgres、MySQL等)还是NoSQL(MongoDB、Amazon的DynamoDB等),都支持事务,因此在此不需要讨论。

ACID

ACID就像CAP一样被过度使用,实际上它是关于向客户端展示单个数据副本而不是实际存在多个数据副本(以增强可用性、容错等为目的),以及数据库用于执行此操作的策略。例如,在Postgres中,在主从分布式系统的情况下,可以选择同步或异步复制,并且使用WAL(Write ahead logs)实现复制,MongoDB也是同样的情况,只是用oplog(Operations Log)替代了WAL,两者都支持流式复制和故障切换。那么差异在哪里?实际上,我找不到NoSql数据库为什么可以轻松扩展的非常强有力的原因。我能说的是NoSql是最新的,所以数据库带有现成的支持水平扩展的功能,例如考虑MongoDB中的Mongos,它们完成所有肮脏的工作,如分片文档,将请求路由到特定的分片等。因此,如果Postgres或MySQL明天推出一些智能分片表的机制,以便大多数相关数据都保存在一个节点中,则可能会结束这场辩论,因为关系型数据库本质上没有任何防止其横向扩展的特性。

乐观地说,我相信在不久的将来,一切都将取决于策略。你如何计划进行扩展,而这些策略将独立于你如何存储数据,无论是在表中还是在文档中。例如,在Amazon的DocumentDB中,存在自动缩放的概念,但如果要通过分片实现这一点,则每次缩放时都需要复制数据,这将是一个负担。在DocumentDB中,共享群集卷(数据存储与计算分离)负责处理这个问题,这只是所有实例(主要或次要)的共享磁盘,并且为了避免共享磁盘故障的风险,DocumentDB将共享磁盘的数据复制到其他6个不同可用区的磁盘上。因此,这里需要注意的是,DocumentDB混合了共享磁盘和标准复制策略的概念,以实现其目标。因此,重要的是您在数据库中使用的策略。


在这种情况下,你真的不理解“去规范化”或“预SQL”,你所谓的“糟糕设计”在No SQL世界中实际上在许多情况下是一个好的设计。 - dontknowhy
@gaesae,我认为这是一种糟糕的设计,因为在这种类型的设计中,更改任何内容都不容易。如果不按照我提到的示例正确进行规范化处理,则需要在多个位置同时进行单个更改。 - manvendra yadav

2

在关系型数据库中,当数据变得非常庞大时,可能会发生表分布在多个系统上的情况,在这种情况下,执行JOIN等操作会非常缓慢。

在NoSQL中,通常将相关数据存储在同一台机器上(要么是单个文档 - 在面向文档的数据库中,要么是在宽列数据存储中,相关列位于同一台机器上)。因此,可以轻松地在许多低端机器上进行扩展,在这种情况下,将存在重复数据在多个位置,而在关系型数据库中则不是这样。

原始答案:Original Answer


0

@jessedrelick在他们的回答中提到了分片,我想深入研究一下这个问题——因为最终这就是让我顿悟的关键点。(而MongoDB有一个解释得非常好的页面。)

让我们举一个极端的例子并简化它,因为我认为这样更容易理解。假设你正在设计一个保存Instagram上所有帖子的数据库。

在关系型数据库中,你会有一个posts表。一开始工作得很好!但随着越来越多的人使用Instagram,帖子数量迅速增长...你最终需要扩展到一个更大的服务器,以便为所有这些新帖子腾出空间,并容纳尝试访问它们的所有流量。(扩展成本高昂,特别是当考虑到您的流量负载不总是相同时,您不希望支付您95%时间未使用的资源。)

而且,如今在Instagram上每天都会创建数以百万计(甚至数十亿)的帖子。你会到达一个需要一些策略来分发数据和请求(扩展)的点。
这就是类似范围分片的东西发挥作用的地方,你的系统会将数据分块到不同的个体节点上,并拥有一个查找表,根据你的需求指向正确的节点。而且,由于较小的(“商品”)节点比庞大的企业级实例更便宜,它还具有一些成本优势。
然而,如果你想利用关系数据库的一些重要优势,比如跨表连接,处理跨不同服务器的数据可能会变得棘手。
现在,我真的不认为有什么阻止你使用RDBMS实现类似范围分片查找系统的。但在那一点上,你已经失去了与关系结构相关的一些关键优势(再次,比如连接)。因此,重新分析是否选择RDBMS或NoSQL可能是值得的。

-1
对于 NO SQL 数据库, 1.所有与集合相关的子项都位于同一位置,因此在同一服务器上,没有联接操作来查找另一个服务器上的数据。
2.没有模式,因此不需要在任何服务器上进行锁定,并且事务处理留给客户端处理。
以上两点节省了 NO-SQL 扩展的许多开销。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接