龙空技术网

如何选择数据库,生活中还有比SQL更重要的东西

闻数起舞 820

前言:

现在你们对“如何选购数据库”大致比较看重,看官们都想要知道一些“如何选购数据库”的相关知识。那么小编在网摘上收集了一些关于“如何选购数据库””的相关资讯,希望兄弟们能喜欢,朋友们快快来了解一下吧!

Danny - 10分钟阅读

无论你是在建立你的第一个还是第五十个应用程序,选择一个数据库是最困难的选择之一。这将是你做出的第一个决定之一,也可能是在你的应用程序中根深蒂固的一个决定。由于有大量优秀的数据库可用,而且有大量现成的信息可用,这只会使任务更加困难。

我们最近的项目,以及WeGift对发展速度的渴望,使得我们有必要转变为事件驱动的架构,这为利用最新的技术提供了很多机会。对于我们最近的项目,我们必须为一个有多个第三方集成的系统选择一个数据库,它将返回不同的元数据,能够促进大量的交易。

在这篇文章中,我将简明扼要地介绍常见的数据库类型,它们的用途,以及选择数据库时应该考虑的一些不太常提到的问题。

数据库的主要类型有哪些?

关系型数据库

例子。PostgreSQL、MySQL、Oracle DB

关系型数据库是最常用的数据库类型。数据被组织在表格中,毫不奇怪,它们之间可以使用外键定义关系。SQL允许你查询这些表并将它们连接起来,允许你以适合你要求的格式有效地检索数据。表的结构是使用列和行,其中列定义了数据属性,行定义了表中的一条记录。

图1:关系型数据库中的表的例子。

关系型数据库确保了ACID交易,这意味着数据的完整性总是被保留下来。ACID事务,再加上在数据插入之前需要定义模型,意味着当数据的一致性和稳定性是行为要求的组成部分时,关系型数据库是完美的。然而,这种稳定性是以灵活性为代价的。

关系型数据库的主要缺点是,当需要大量交易时,或者数据库的地理位置很重要时,性能的可扩展性。典型的用于扩展关系型数据库的第一个端口是垂直扩展,增加更多的计算能力。然而,这当然有其局限性。除此之外,还需要引入分片、缓存和读取副本的使用,但这导致了解决这些问题的额外工作,而这些工作往往只有在数据库明显成为瓶颈时才会被意识到。

关系型数据库的完美用例是当所需的数据一致性很高,并且关系被很好地定义。一个电子商务平台的报告系统,其中有包括客户、订单、付款和产品的表格,将是关系型数据库的完美候选者。原因是关系被很好地定义,需要利用交易,并且需要使用关系来执行定制的查询,以进行分析或报告。关系型数据库的另一个不言而喻的好处是有大量的文件可用,这使得开发过程更加容易。

图数据库

例子。Amazon Neptune, Neo4j

图形数据库使用节点(定义存储的数据)和边(存储节点之间的关系)来定义。这种关系的存储意味着连接这些数据集是非常快的,相反,关系型数据库会在查询时计算这些数据,使整个过程变慢。

图2:简化图数据库的一个例子。

利用图形数据库的独特功能需要一种优化的查询语言,这导致了许多不同的查询语言,如Cypher、SparQL和Gremlin。这些查询语言采用模式匹配来提取数据。例如,如果我想直接查询Rob认识的人,一个查询可以是这样的。

MATCH (a:Person {name: "Rob"})-[:KNOWS]->(b)。

RETURN b

直观地说,图形数据库非常适合于存储事物之间的联系数据,例如社交网络上的朋友、广告显示或欺诈预防。相反,它们不太适合存储诸如交易历史的东西。每个数据库对ACID交易的支持和扩展能力各不相同,所以在选择之前值得研究一下。

文档数据库

例子。MongoDB, CouchDB, ElasticSearch

文档数据库通常将数据存储为结构化的嵌套文档(想想JSON/BSON,XML),这意味着它们直观地对应于你代码中的对象。这些文档被存储在集合中,类似于关系数据库中的行和表。

图3:一个文件的例子。

文档允许你使用灵活的模式来存储半结构化的信息,允许你由于不断变化的需求而轻松更新。在这方面,这是与关系型数据库的主要区别之一,后者需要一个SQL语句来更新模式。这种灵活性使文档数据库非常适合于存储任何可能有不同内容的东西,但你需要灵活的查询;想想产品信息或客户细节。

大多数文档数据库都以某种形式支持连接功能,然而,文档的设计使用方式意味着你通常不应该这样做。例如,在关系型数据库中,一个客户和客户的联系方式通常会被存储在两个独立的表中,但是在文档数据库中,你会利用分层结构将它们存储在一个文档中。

大多数文档数据库也支持ACID事务,并且通常支持水平扩展;这种扩展允许你支持巨大的读取查询量。MongoDB还支持强一致性(线性化),这总是很方便。

键/值数据库

例如。Redis, Berkeley DB

键/值存储是概念上最简单的数据库;它是一种非关系型数据库,其中的值是针对键来存储的。这些值可以是简单的单项数据,也可以是更复杂的对象,类似于文档。这听起来与文档数据库极为相似,然而在键/值数据库中,针对键存储的信息不太透明。这意味着,对于文档数据库来说,你可以针对非主键进行查询,允许更高的灵活性,而对于键/值数据库来说,你通常只能针对一个主键进行查询。

虽然键/值数据库的灵活性较低,但这导致了更好的读和写性能,所以也有好处当你知道你要查询什么时,它们是最好用的。然后,找到一个已知的键的信息是非常快的,然而,如果你需要通过一个非主键过滤,这就变得更加困难。

键/值数据库的使用情况与文档数据库非常相似;用户档案、会话数据或简单的缓存数据。与文档数据库一样,它们通常也支持横向扩展。

宽列数据库

例子。Apache Cassandra, Bigtable, ScyllaDB

在查询大数据以生成分析和报告时,你很少希望查询每一行的每一列,这样做的效率相当低。即使减少所选列的数量,这仍然会导致大量不必要的数据被解析!宽列/列族数据库,通过在列中划分数据来规避这个问题,当需要查询时,只检索所需的列。这样做的结果是一个分区列的稀疏矩阵,包含一个单一的数据类型(宽列),或存储一行的列族,而这一行又有嵌套的列和值在其内部。

图4:宽列/列族数据库结构的例子。

宽列数据库对于诸如数据记录、报告甚至消息服务都是非常棒的--Discord写了一篇关于他们从MongoDB迁移到Apache Cassandra的精彩文章。他们的最佳用例是当你有可预测的查询模式,高写入和低读取频率的要求。稀疏矩阵设计允许在数据库内有很高的灵活性;一行不一定要使用所有的列,这意味着不同的行可以由不同的列组成。

宽列数据库通常以较低的线性化(由于水平缩放)来交换这种高写入速度,这意味着当你查询时,你不能保证获得最新的写入信息。

选择数据库时需要考虑的因素

CAP和ACID中的C非常不同,不是特别重要。

我经常看到有两个概念被混淆了,那就是CAP和ACID中的C;虽然两者在这些缩写中都代表着一致性,但它们本质上是两种完全不同的东西。

从ACID中的C开始,这里的一致性意味着关于你的数据的某些约束或声明必须始终被遵守;无论是这种类型、某些组合、限制还是唯一性。然而,这就是数据库在一致性方面的能力限制--任何更复杂的东西都不能由数据库来处理。大多数数据库默认提供这种级别的一致性,它不能替代由业务逻辑产生的不变性,随后也不能阻止忽略这些的事务完成。因此,在我看来,原子性、隔离性和持久性是数据库所提供的更重要的特性,也是你应该更重视的东西。

相反,CAP中的C(见这篇文章中CAP的缺陷),最好被称为线性化,它可以简单地分解为:当一个数据库被写入时,任何后续的读取都会看到刚刚被写入的确切数据。你可以想象,在某些应用中,这一点是至关重要的--例如,在下订单之前检查客户的余额,或者产品的库存水平。

图5:缺乏可线性化如何影响应用行为的例子。

很多数据库尽管有复制,但可以提供线性化,虽然它不是即时的,但复制之间的延迟可以快到对你的应用没有实际影响。线性化也不是一个数据库的基本质量,通过牺牲它,你可以在其他方面获得好处,比如说读写速度。不需要高线性度的例子可以是一个报告系统,它汇总了订单量或有多少用户喜欢一个社交媒体帖子--任何不需要精确实时值的地方。

需要什么样的关系?

当查询你的数据时,需要什么样的关系?在我看来,这是区别上述数据库类型的最大因素之一;而不是SQL与NOSQL。这个问题在很大程度上取决于你的应用程序的预期行为,以及它所构建的架构。

在这方面没有一个放之四海而皆准的数据库,也不应该有人幻想使用单一的数据库类型是唯一的方法;单独的服务可能需要完全不同的数据库。当首先决定你希望使用什么数据库时,对你的数据进行建模--定义实体和关系,这很可能会清楚哪种数据库最适合你。同样相关的是,拥有关系并不是必须的,如果你能以一种避免这些关系的方式来构造你的数据,就能使你的应用程序的性能受益;关系总是有代价的。

要求 - 它们是众所周知的吗?

这个问题相当广泛,可能意味着大量的先决条件,从功能性到非功能性。除了应用行为之外,还有无数可能的要求;你是否被锁定在一个云供应商?你需要一个完全管理的服务吗?安全性有多重要?所有这些东西都不会被认为是前几节中的主要要求,但是它们都在选择数据库的动态过程中起着很大的作用。

当你考虑在你的主机生态系统之外的选择时,你会发现自己花在管理这些解决方案上的时间远远超过最初的预算--安全更新、故障转移和备份。当然,这些都是次要的,因为数据库的主要要求和他们给你的能力,但是必须考虑这些因素以避免进一步的头痛。

结论。我们是如何驾驭这个仙境的?

这些考虑,再加上敏捷开发中对快速移动和快速迭代的渴望,意味着在开发过程的早期花费时间将得到回报--在后期阶段的迁移是昂贵的,最好是避免的。这个决定不仅会影响你的应用程序的性能,也会影响开发过程。

上面列出的因素并不是唯一需要考虑的因素,它们是我认为经常被忽视的因素。我彻底建议花大量时间审查和测试尽可能多的选择,以了解每个可用选择之间的根本区别。

在我们自己经历了这个过程之后,我们在键/值和文档混合数据库和文档数据库之间选择了一个。我们把范围缩小到DynamoDB和DocumentDB之间--AWS的一个MongoDB分叉。

首先,在WeGift,我们目前的基础设施都在AWS上;我们希望有一个管理服务来执行安全更新、备份和扩展。这两点都支持强一致性的读取,这也是我们作为这个功能的一部分所需要的。

最后,模式的灵活性非常适合我们的要求;我们将从第三方供应商那里存储不同的元数据,而拥有良好的开发者体验的愿望在我们的清单上名列前茅;不必编写模式迁移肯定有助于实现这一点。我们将花一些时间对两者进行试验,当我们得出结论时,我一定会更新这个帖子。

请很快回来看看我们选择了哪种方案!

标签: #如何选购数据库 #关系型数据库不能处理表间的什么关系