百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

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

wptr33 2025-03-05 22:04 20 浏览

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上;我们希望有一个管理服务来执行安全更新、备份和扩展。这两点都支持强一致性的读取,这也是我们作为这个功能的一部分所需要的。

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

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

相关推荐

MySQL进阶五之自动读写分离mysql-proxy

自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...

Postgres vs MySQL_vs2022连接mysql数据库

...

3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?

引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...

一文由浅入深带你完全掌握MySQL的锁机制原理与应用

本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...

验证Mysql中联合索引的最左匹配原则

后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...

MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

目录1.索引基础...

你会看 MySQL 的执行计划(EXPLAIN)吗?

SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...

MySQL 从入门到精通(四)之索引结构

索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...

mysql总结——面试中最常问到的知识点

mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...

mysql总结——面试中最常问到的知识点(2)

首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...

MySQL基础全知全解!超详细无废话!轻松上手~

本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...

深入剖析 MySQL 中的锁机制原理_mysql 锁详解

在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...

Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析

引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...

MySQL基础篇:DQL数据查询操作_mysql 查

一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...

MySql:索引的基本使用_mysql索引的使用和原理

一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...