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