在开发一个应用程序时,不可避免要选择使用SQL还是NoSQL数据库来存储数据。传统的数据库,即使用SQL(结构化查询语言)进行查询的关系型数据库,是经过几十年来技术发展、良好实践和现实世界压力测试的产物。它们是为可靠的事务和临时查询而设计的,是业务线应用的主力军。但它们也有一些限制,如严格的模式,使它们不太适合于其他类型的应用。
NoSQL数据库是针对这些限制而产生的。NoSQL系统存储和管理数据的方式,允许高操作速度,并让开发人员有巨大灵活性。许多数据库是由谷歌、亚马逊、雅虎和Facebook等公司开发的,它们寻求更好的方式来存储内容或处理大型网站的数据。与SQL数据库不同,许多NoSQL数据库可以在数百或数千台服务器上进行横向扩展。
不过,NoSQL的优势并不是没有代价的。NoSQL系统倾向于速度和可扩展性,而不是SQL数据库所承诺的可靠事务背后的ACID属性。与围绕SQL建立的数十年的机构知识相比,在NoSQL系统中用于处理数据的隐喻也是相对较新的。
SQL和NoSQL数据库提供了不同的权衡。虽然它们在特定项目的背景下可能会有竞争,例如,为不同应用会面临二选一的情况,但它们在更大范围内是互补的,每一种都适合于不同的使用情况。是选择SQL还是NoSQL并不是绝对的,要根据场景需求选合适的。
NoSQL与SQL
SQL和NoSQL之间的根本区别并不那么复杂。对于如何存储和检索数据,两者都有不同的理念。
对于SQL数据库,所有数据都有一个固有的结构。像Microsoft SQL Server、MySQL、PostgreSQL或Oracle数据库这样的传统数据库使用一个模式--对插入数据库的数据如何组成的正式定义。例如,一个表中的某一列可能被限制为只能是整数。因此,记录在该列中的数据将有很高的规范化程度。SQL数据库的严格模式也使得对数据进行聚合变得相对容易,例如,使用SQL JOIN命令将两个表的数据合并。
在NoSQL中,数据可以以无模式或自由的方式存储。任何数据都可以存储在任何记录中。在NoSQL数据库中,你会发现四种常见的数据存储模式,这导致了四种常见的NoSQL系统类型。
- 文档数据库(如MongoDB)。插入的数据以无模式的JSON结构或“文档”的形式存储,其中的数据可以是任何东西,从整数到字符串再到自由格式的文本。没有必要指定JSON文档将包含哪些字段(如果有的话)。
- 键值存储(如Redis)。自由格式的值,从简单的整数或字符串到复杂的JSON文档,都可以通过键(比如字符串)在数据库中访问。
- 宽列存储(如 Cassandra)。数据被存储在列中,而不是像传统SQL系统存储在行。任何数量的列(以及许多不同类型的数据)都可以根据查询或数据视图的需要进行分组或聚合。
- 图数据库(如Neo4j)。数据被表示为实体及其关系的网络或图形,其中图中的每个节点是一个自由形式的数据块。
无模式的数据存储在以下情况下是有用的。
- 你想快速访问数据,你更关心访问的速度和简单性,而不是可靠的事务或一致性。
- 你正在存储大量的数据,你不想把自己锁定在一个模式中,因为以后改变模式可能是缓慢和痛苦的。
- 你正在从一个或多个来源接收非结构化数据,你想保持数据的原始格式以获得最大的灵活性。
- 你想把数据存储在一个分层结构中,但你希望这些分层结构由数据本身来描述,而不是外部模式。NoSQL允许数据随意地自我引用,该方式对于SQL数据库来说更为复杂,难以模仿。
查询NoSQL数据库
关系型数据库使用的结构化查询语言提供了一种统一的方式,在存储和检索数据时与服务器通信。SQL语法是高度标准化的,所以尽管各个数据库可能会以不同的方式处理某些操作(例如,窗口函数),但基本原理仍然是相同的。
相比之下,每个NoSQL数据库往往都有自己的语法来查询和管理数据。例如,CouchDB使用JSON形式的请求,通过HTTP发送,以创建或检索其数据库中的文档。MongoDB通过二进制协议,以命令行接口或语言库的方式发送JSON对象。
一些NoSQL产品可以使用类似SQL的语法来处理数据,但只是在有限的范围内。例如,Apache Cassandra,一个广泛的列存储,有自己的类似SQL的语言,Cassandra查询语言(CQL)。CQL的一些语法是直接来自于SQL的手册,比如SELECT或INSERT关键字。但在Cassandra中没有执行JOIN或子查询的本地方法,因此相关的关键字在CQL中并不存在。
无共享shared-nothing架构
NoSQL系统常见的一个设计选择是“shared-nothing”架构。在一个无共享的设计中,集群中的每个服务器节点都独立于其他节点运行。系统不需要从其他节点获得共识来返回数据给客户端。查询速度很快,因为它们可以从最近的或最方便的节点返回。
无共享系统的另一个优点是弹性和向外扩展。向外扩展集群非常容易,只需旋转集群中的新节点并等待它们与其他节点同步即可。如果一个NoSQL节点宕机,集群中的其他服务器将继续运行。即使服务请求的节点减少,所有数据仍然可用。
请注意,无共享的设计并不是NoSQL数据库所独有的。许多传统的SQL系统可以以无共享的方式设置,如MySQL,尽管这通常涉及到牺牲整个集群的一致性以获得性能。
NoSQL的局限性
如果NoSQL提供了如此多的自由和灵活性,为什么不完全放弃SQL?答案很简单,许多应用仍然需要SQL数据库所提供的各种约束、一致性和保障措施。在这些情况下,NoSQL的一些“优势”可能会变成劣势。其他的限制来自于NoSQL系统缺乏某些在SQL领域中本应有的功能。
(1) 无模式(No schema)
即使你接收的是自由格式的数据,你也几乎总是需要对数据施加约束,以使其有用。对于NoSQL,施加约束涉及到将责任从数据库转移到应用开发者身上。例如,开发者可以通过一个对象关系映射系统(或称ORM)强加结构。但如果你想让模式与数据本身共存,NoSQL通常不支持这种做法。
一些NoSQL解决方案为数据提供了可选的数据类型和验证机制。例如,Apache Cassandra有一系列的本地数据类型,让人想起传统SQL中的那些数据类型。
(2) 最终一致性
NoSQL系统提供了强一致性或即时一致性的选择,以获得更好的可用性和性能。传统的数据库确保操作是原子的(事务的所有部分都成功,或者没有一个成功)、一致的(所有用户都有相同的数据视图)、隔离的(事务不竞争)和持久的(一旦完成,它们将不受服务器故障的影响)。
这四个属性,统称为ACID,在NoSQL系统中可以用不同的方式处理。你可以选择最终一致性,而不是要求整个集群的强一致性,这必然会延迟对请求的响应,允许服务请求,而无需等待最新的写入复制到集群的其它节点。插入集群的数据最终在各处都是可用的,但不能保证任何时候可用。
对于一些NoSQL系统,你可以在一致性和速度之间选择一个折中方案,不同的产品有不同的方案。例如,微软的Azure Cosmos DB可以让你选择每个请求的一致性级别,所以你可以选择适合你的。事务语义,在SQL系统中保证事务中的所有步骤(例如执行销售和减少库存)要么完成,要么回滚,在一些NoSQL系统中也有,例如MongoDB。
(3) NoSQL的锁定
大多数NoSQL系统在概念上是相似的,但实现方式不同。每个系统都有自己的隐喻和机制,用于数据的查询和管理。
这样做的一个副作用是应用逻辑和数据库之间可能存在高度的耦合。如果你选择一个NoSQL系统并坚持使用它,这种耦合性并没有什么坏处,但如果你在未来更换系统,它就会成为一个绊脚石。
如果你从MongoDB迁移到CouchDB(或者相反),你需要做的不仅仅是迁移数据。还必须驾驭数据访问和编程隐喻之间的差异。换句话说,你必须重写应用程序中访问数据库的部分。
(4) NoSQL技能
NoSQL的另一个缺点是相对缺乏专业知识。传统SQL人才的市场相当大,而NoSQL技能的市场却刚刚起步。
作为参考,Indeed.com报告称,截至2022年,传统SQL数据库(MySQL、微软SQL Server、Oracle数据库等)的职位数量仍然高于MongoDB、Couchbase和Cassandra的职位数量。对NoSQL专业知识的需求仍然只是SQL技能市场的一小部分。
合并SQL和NoSQL
未来,随着时间的推移,SQL和NoSQL系统之间的一些差异会消失。现在已经有许多SQL数据库接受JSON文档作为原生数据类型,并可以对该数据进行查询。一些数据库甚至有对JSON数据施加约束的本地方法,因此其处理方式与传统的行和列数据一样严格。
另一方面,NoSQL数据库不仅增加了类似SQL的查询语言,还增加了传统SQL数据库的其他功能,比如MongoDB的ACID属性。
一个可能的路径是,未来几代数据库以及当前数据库系统的未来版本将跨越这些范式,同时提供SQL和NoSQL功能,有助于使数据库世界不再支离破碎。例如,微软的Azure Cosmos DB在底层使用了一套基元,可以互换地再现两种系统的行为。谷歌云Spanner将SQL的强一致性与NoSQL系统的水平可扩展性相结合。
不过,纯SQL和纯NoSQL系统仍将在未来很多年占有一席之地。在设计灵活性、水平扩展性和高可用性比强读一致性和其他SQL数据库常见的保障措施更重要的情况下,可以考虑使用NoSQL。对于许多应用来说,这些保障措施很可能值得用来交换NoSQL所提供的东西。
对于许多应用程序来说,以NoSQL的特有优势来那些换保障措施是值得。
免责声明:本平台仅供信息发布交流之途,请谨慎判断信息真伪。如遇虚假诈骗信息,请立即举报
举报