数据库对比 Nosql vs Sql

2021/01/09 Database 共 10132 字,约 29 分钟

数据库对比

参考

关系型数据库管理系统(RDBMS)

像 SQL 这样的关系型数据库是一系列以表的形式组织的数据项集合。

ACID 用来描述关系型数据库事务的特性。

  • 原子性 - 每个事务内部所有操作要么全部完成,要么全部不完成。
  • 一致性 - 任何事务都使数据库从一个有效的状态转换到另一个有效状态。
  • 隔离性 - 并发执行事务的结果与顺序执行事务的结果相同。
  • 持久性 - 事务提交后,对系统的影响是永久的。

关系型数据库扩展包括许多技术:主从复制、主主复制、联合、分片、非规范化和 SQL调优。

主从复制

主库同时负责读取和写入操作,并复制写入到一个或多个从库中,从库只负责读操作。树状形式的从库再将写入复制到更多的从库中去。如果主库离线,系统可以以只读模式运行,直到某个从库被提升为主库或有新的主库出现。

不利之处:主从复制
  • 将从库提升为主库需要额外的逻辑。
  • 参考不利之处:复制中,主从复制和主主复制共同的问题。

主主复制

两个主库都负责读操作和写操作,写入操作时互相协调。如果其中一个主库挂机,系统可以继续读取和写入。

不利之处: 主主复制
  • 你需要添加负载均衡器或者在应用逻辑中做改动,来确定写入哪一个数据库。
  • 多数主-主系统要么不能保证一致性(违反 ACID),要么因为同步产生了写入延迟。
  • 随着更多写入节点的加入和延迟的提高,如何解决冲突显得越发重要。
  • 参考不利之处:复制中,主从复制和主主复制共同的问题。
不利之处:复制
  • 如果主库在将新写入的数据复制到其他节点前挂掉,则有数据丢失的可能。
  • 写入会被重放到负责读取操作的副本。副本可能因为过多写操作阻塞住,导致读取功能异常。
  • 读取从库越多,需要复制的写入数据就越多,导致更严重的复制延迟。
  • 在某些数据库系统中,写入主库的操作可以用多个线程并行写入,但读取副本只支持单线程顺序地写入。
  • 复制意味着更多的硬件和额外的复杂度。

联合(按功能分库)

联合(或按功能划分)将数据库按对应功能分割。例如,你可以有三个数据库:论坛、用户和产品,而不仅是一个单体数据库,从而减少每个数据库的读取和写入流量,减少复制延迟。较小的数据库意味着更多适合放入内存的数据,进而意味着更高的缓存命中几率。没有只能串行写入的中心化主库,你可以并行写入,提高负载能力。

不利之处:联合
  • 如果你的数据库模式需要大量的功能和数据表,联合的效率并不好。
  • 你需要更新应用程序的逻辑来确定要读取和写入哪个数据库。
  • 用 server link 从两个库联结数据更复杂。
  • 联合需要更多的硬件和额外的复杂度。

分片

分片将数据分配在不同的数据库上,使得每个数据库仅管理整个数据集的一个子集。以用户数据库为例,随着用户数量的增加,越来越多的分片会被添加到集群中。

类似联合的优点,分片可以减少读取和写入流量,减少复制并提高缓存命中率。也减少了索引,通常意味着查询更快,性能更好。如果一个分片出问题,其他的仍能运行,你可以使用某种形式的冗余来防止数据丢失。类似联合,没有只能串行写入的中心化主库,你可以并行写入,提高负载能力。

常见的做法是用户姓氏的首字母或者用户的地理位置来分隔用户表。

不利之处:分片
  • 你需要修改应用程序的逻辑来实现分片,这会带来复杂的 SQL 查询。
  • 分片不合理可能导致数据负载不均衡。例如,被频繁访问的用户数据会导致其所在分片的负载相对其他分片高。
    • 再平衡会引入额外的复杂度。基于一致性哈希的分片算法可以减少这种情况。
  • 联结多个分片的数据操作更复杂。
  • 分片需要更多的硬件和额外的复杂度。

非规范化

非规范化试图以写入性能为代价来换取读取性能。在多个表中冗余数据副本,以避免高成本的联结操作。一些关系型数据库,比如 PostgreSQl 和 Oracle 支持物化视图,可以处理冗余信息存储和保证冗余副本一致。

当数据使用诸如联合和分片等技术被分割,进一步提高了处理跨数据中心的联结操作复杂度。非规范化可以规避这种复杂的联结操作。

在多数系统中,读取操作的频率远高于写入操作,比例可达到 100:1,甚至 1000:1。需要复杂的数据库联结的读取操作成本非常高,在磁盘操作上消耗了大量时间。

不利之处:非规范化
  • 数据会冗余。
  • 约束可以帮助冗余的信息副本保持同步,但这样会增加数据库设计的复杂度。
  • 非规范化的数据库在高写入负载下性能可能比规范化的数据库差。
来源及延伸阅读:非规范化

SQL 调优

SQL 调优是一个范围很广的话题,有很多相关的书可以作为参考。

利用基准测试和性能分析来模拟和发现系统瓶颈很重要。

  • 基准测试 - 用 ab 等工具模拟高负载情况。
  • 性能分析 - 通过启用如慢查询日志等工具来辅助追踪性能问题。

基准测试和性能分析可能会指引你到以下优化方案。

改进模式
  • 为了实现快速访问,MySQL 在磁盘上用连续的块存储数据。

  • 使用CHAR类型存储固定长度的字段,不要用VARCHAR

    • CHAR 在快速、随机访问时效率很高。如果使用 VARCHAR,如果你想读取下一个字符串,不得不先读取到当前字符串的末尾。
  • 使用 TEXT 类型存储大块的文本,例如博客正文。TEXT 还允许布尔搜索。使用 TEXT 字段需要在磁盘上存储一个用于定位文本块的指针。

  • 使用 INT 类型存储高达 2^32 或 40 亿的较大数字。

  • 使用 DECIMAL 类型存储货币可以避免浮点数表示错误。

  • 避免使用 BLOBS 存储对象,存储存放对象的位置。

  • VARCHAR(255) 是以 8 位数字存储的最大字符数,在某些关系型数据库中,最大限度地利用字节。

  • 在适用场景中设置 NOT NULL 约束来提高搜索性能。

使用正确的索引
  • 你正查询(SELECT、GROUP BY、ORDER BY、JOIN)的列如果用了索引会更快。
  • 索引通常表示为自平衡的 B 树,可以保持数据有序,并允许在对数时间内进行搜索,顺序访问,插入,删除操作。
  • 设置索引,会将数据存在内存中,占用了更多内存空间。
  • 写入操作会变慢,因为索引需要被更新。
  • 加载大量数据时,禁用索引再加载数据,然后重建索引,这样也许会更快。
避免高成本的联结操作
  • 有性能需要,可以进行非规范化。
分割数据表
  • 将热点数据拆分到单独的数据表中,可以有助于缓存。
调优查询缓存

NoSQL

NoSQL 是键-值数据库、文档型数据库、列型数据库或图数据库的统称。数据库是非规范化的,表联结大多在应用程序代码中完成。大多数 NoSQL 无法实现真正符合 ACID 的事务,支持最终一致。

BASE 通常被用于描述 NoSQL 数据库的特性。相比 CAP 理论,BASE 强调可用性超过一致性。

  • 基本可用 - 系统保证可用性。
  • 软状态 - 即使没有输入,系统状态也可能随着时间变化。
  • 最终一致性 - 经过一段时间之后,系统最终会变一致,因为系统在此期间没有收到任何输入。

除了在 SQL 还是 NoSQL 之间做选择,了解哪种类型的 NoSQL 数据库最适合你的用例也是非常有帮助的。我们将在下一节中快速了解下 键-值存储、文档型存储、列型存储和图存储数据库。

键-值存储

抽象模型:哈希表

键-值存储通常可以实现 O(1) 时间读写,用内存或 SSD 存储数据。数据存储可以按字典顺序维护键,从而实现键的高效检索。键-值存储可以用于存储元数据。

键-值存储性能很高,通常用于存储简单数据模型或频繁修改的数据,如存放在内存中的缓存。键-值存储提供的操作有限,如果需要更多操作,复杂度将转嫁到应用程序层面。

键-值存储是如文档存储,在某些情况下,甚至是图存储等更复杂的存储系统的基础。

来源及延伸阅读

实现

  • redis内存,hashmap 和 跳表当zset
  • lsm树,分层的有序结构,分层合并merge。 二分查找。

文档类型存储

抽象模型:将文档作为值的键-值存储

文档类型存储以文档(XML、JSON、二进制文件等)为中心,文档存储了指定对象的全部信息。文档存储根据文档自身的内部结构提供 API 或查询语句来实现查询。请注意,许多键-值存储数据库有用值存储元数据的特性,这也模糊了这两种存储类型的界限。

基于底层实现,文档可以根据集合、标签、元数据或者文件夹组织。尽管不同文档可以被组织在一起或者分成一组,但相互之间可能具有完全不同的字段。

MongoDB 和 CouchDB 等一些文档类型存储还提供了类似 SQL 语言的查询语句来实现复杂查询。DynamoDB 同时支持键-值存储和文档类型存储。

文档类型存储具备高度的灵活性,常用于处理偶尔变化的数据。

来源及延伸阅读:文档类型存储

实现

MongoDB 中的文档类似于关系数据库中的一行数据,但它是结构化的,存储为键值对。每个文档在 MongoDB 中都是一个独立的实体,并可以具有灵活的结构。与关系型数据库不同,MongoDB 允许不同文档有不同的字段,甚至字段的类型也可以不同,这种灵活性使得 MongoDB 特别适合于需要快速迭代和灵活存储的数据模型。

ES底层也是基于Big Table这种LSM来构建的词id -> doc id列表的索引。

列型存储

抽象模型:嵌套的 ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>> 映射

类型存储的基本数据单元是列(名/值对)。列可以在列族(类似于 SQL 的数据表)中被分组。超级列族再分组普通列族。你可以使用行键独立访问每一列,具有相同行键值的列组成一行。每个值都包含版本的时间戳用于解决版本冲突。

Google 发布了第一个列型存储数据库 Bigtable,它影响了 Hadoop 生态系统中活跃的开源数据库 HBase 和 Facebook 的 Cassandra。像 BigTable,HBase 和 Cassandra 这样的存储系统将键以字母顺序存储,可以高效地读取键列。

列型存储具备高可用性和高可扩展性。通常被用于大数据相关存储。

大家都知道HDFS是分布式文件系统,hbase是基于HDFS的KV数据库,这两者的关系和GFS、BigTable的关系如出一辙

来源及延伸阅读:列型存储

列式数据库:

1.数据是按列存储的,每一列单独存放

2.数据既是索引

3.只访问查询涉及的列,大量降低系统io

4.每一列有一个线程来处理,支持查询的高并发

5.数据类型一致,数据特征相似,高效的压缩

为什么可以大量降低系统io: 复制代码比如查询表中所有人的名字;行式数据库需要查询所有行,列式数据库只需要查询name列.

图数据库

抽象模型: 图

在图数据库中,一个节点对应一条记录,一个弧对应两个节点之间的关系。图数据库被优化用于表示外键繁多的复杂关系或多对多关系。

图数据库为存储复杂关系的数据模型,如社交网络,提供了很高的性能。它们相对较新,尚未广泛应用,查找开发工具或者资源相对较难。许多图只能通过 REST API 访问。

相关资源和延伸阅读:图
来源及延伸阅读:NoSQL

ByteGraph.

HDFS

比如百度网盘等应用就是类似做法。

HDFS(Hadoop Distributed File System ),意为:Hadoop分布式文件系统。它是Apache Hadoop核心组件之一,作为大数据生态圈最底层的分布式存储服务而存在。也可以说大数据首先要解决的问题就是海量数据的存储问题。

  • HDFS主要是解决大数据如何存储问题的。分布式意味着是HDFS是横跨在多台计算机上的存储系统。
  • HDFS是一种能够在普通硬件上运行的分布式文件系统,它是高度容错的,适应于具有大数据集的应用程序,它非常适于存储大型数据 (比如 TB 和 PB)。
  • HDFS使用多台计算机存储文件, 并且提供统一的访问接口, 像是访问一个普通文件系统一样使用分布式文件系统。

HFDS采用分布式的架构,可能有成百上千的服务器组成,每一个组件都有可能出现故障。因此故障检测和自动快速恢复是HDFS的核心架构目标,下面是HDFS的官方架构图:

img

主从架构

HDFS集群是标准的master/slave主从架构集群,一般一个HDFS集群是有一个Namenode和一定数目的DataNode组成。

主角色:NameNode

  • NameNode是Hadoop分布式文件系统的核心,架构中的主角色。 
  • NameNode维护和管理文件系统元数据,包括名称空间目录树结构、文件和块的位置信息、访问权限等信息。 
  • 基于此,NameNode成为了访问HDFS的唯一入口。

从角色:DataNode

  • DataNode是Hadoop HDFS中的从角色,负责具体的数据块存储。 
  • DataNode的数量决定了HDFS集群的整体数据存储能力,通过和NameNode配合维护着数据块。

主角色辅助角色: SecondaryNameNode

此外,HDFS中还有一个SecondaryNameNode,虽然途中没有画出,那它有什么用呢?

  • Secondary NameNode充当NameNode的辅助节点,但不能替代NameNode。 
  • 主要是帮助主角色进行元数据文件的合并动作。可以通俗的理解为主角色的“秘书”。

分块存储

由于有的文件很大,一台机器也存不下,于是HDFS会对我们的文件做一个物理上的切割,也就是分块存储。

HDFS中的文件在物理上是分块存储(block)的,默认大小是128M(134217728),不足128M则本身就是一块。

img

副本机制

既然分布式存储海量数据,那么肯定需要成千上百的机器,这样很有可能其中一台机器宕机,出故障了怎么办呢?

当然HDFS也想到了解决方案,文件的所有block都会有副本。副本系数可以在文件创建的时候指定,也可以在之后通过命令改变。副本数由参数dfs.replication控制,默认值是3,也就是会额外再复制2份,连同本身总共3份副本,而且这个副本尽量会分散在不同的机架上,规避风险。

时序型数据库

参考

理论下,常规数据库可以支持时间序列数据, 但是需要数据库专家级别的调优后,才能满足数据量比较大的场景需求。

具体点说,关系型数据库没有对时间序列数据进行优化,有以下几点原因

  • 在滚动时间窗口中计算平均值,需要编写复杂且难以阅读的 SQL。
  • 为了支持标签(tag/label)数据,我们需要给每个标签加一个索引。
  • 相比之下,关系型数据库在持续的高并发写入操作时表现不佳。

相比之下,专门对时间序列数据优化的时序数据库,更适合这种场景。

OpenTSDB 是一个分布式时序数据库,但由于它基于 Hadoop 和 HBase,运行 Hadoop/HBase 集群也会带来复杂性。Twitter 使用了 MetricsDB 时序数据库存储指标数据,而亚马逊提供了 Timestream 时序数据库服务。

根据 DB-engines 的报告,两个最流行的时序数据库是 InfluxDB 和 Prometheus ,它们可以存储大量时序数据,并支持快速地对这些数据进行实时分析。

如下图所示,8 核 CPU 和 32 GB RAM 的 InfluxDB 每秒可以处理超过 250,000 次写入。

InfluxDB 使用的针对于时序数据的 Flux 查询语言会更简单更好理解,如下

from(db:"telegraf")
  |> range(start:-1h)
  |> filter(fn: (r) => r._measurement == "foo")
  |> exponentialMovingAverage(size:-10s)

Tag 主要用于对数据进行 过滤 和 分组 操作。由于 Tag 是经常被用来做查询条件的字段,所以它们通常会被索引以提高查询效率。

Field(字段)则是实际存储数据的部分,它是 Tag 的对立面,Field 不是索引的,查询时需要扫描整个数据表。

‌InfluxDB的读音是[‘ɪnflʌks]‌

  • 高效写入:InfluxDB 采用了专门的存储引擎优化数据的写入速度。它使用了 Log-Structured Merge Tree (LSM-Tree) 存储引擎,确保在大量并发写入时,能够保持良好的写入性能。
    • 在 InfluxDB 的 LSM-Tree 实现中,key 由 Measurement、Tag 和 Time 组成,用来唯一标识每个时间序列数据点。value 存储的是 field 数据,即实际的测量值(如温度、湿度等)。通过时间戳和有序存储,InfluxDB 能够高效地执行时间范围查询,同时利用 MemTable 和 SSTables 来优化写入和查询性能。合并(Compaction)操作通过删除重复数据、压缩存储和优化磁盘空间来确保系统的高效运行。
  • 时间序列数据压缩:InfluxDB 在存储时会对数据进行压缩,尤其是对时间序列数据中相似数据的压缩。这大大减少了存储空间的需求。它采用了 TSSD (Time-Structured Merge Tree) 结构进行存储,支持高效的数据压缩和合并。
    • TSSD 使用的是基于时间的分层合并策略,这与传统的 LSM-Tree 合并策略有所不同。具体来说,TSSD 会根据时间顺序将数据分层存储,每个层包含一定时间范围内的数据。例如,第一层存储最新的数据,第二层存储稍早的数据,依此类推。合并过程中,InfluxDB 会选择具有相同时间范围的 SSTables 进行合并。
    • 压缩,比如差分编码:利用相邻数据点之间的差值进行编码,而不是直接存储每个数据点的完整值。这样可以大大减少存储空间需求,特别是在数据变化较小时

InfluxDB 对 Tag 的每个键(key)都创建一个倒排索引,该索引的结构如下:

  • Key:Tag 键名(例如 location)。
  • Value:包含该键的所有数据点的 ID 或时间戳。每个包含该 Tag 的数据点都会在该倒排索引中列出。

例如,如果你有多个数据点都包含 location=us-east-1,倒排索引会记录哪些数据点的 location 是 us-east-1。这样,当你执行查询时,InfluxDB 可以快速根据索引找到所有符合条件的记录。

  • 索引存储在内存中:为了提高查询性能,InfluxDB 会将 Tag 索引的数据存储在内存中(使用 LSM-Tree 和类似 Redis 的数据结构),并定期将其持久化到磁盘。
  • 支持多值索引:每个 Tag 可以具有多个不同的值,倒排索引会记录每个值对应的时间序列数据点。

倒排索引的存储通常使用高效的 B+ 树 或 跳表(Skip List)等数据结构。通过这些数据结构,倒排索引能够支持快速的查找、插入和删除操作。

  • B+ 树:对于磁盘上的数据,倒排索引通常会存储在 B+ 树 结构中,这样可以利用 B+ 树的有序性实现高效的范围查询(如时间区间查询)。
  • 跳表(Skip List):在内存中的倒排索引结构可能使用 跳表,它支持快速的查询和范围查找。

选型

SQL 还是 NoSQL

选取 SQL 的原因:

  • 结构化数据
  • 严格的模式
  • 关系型数据
  • 需要复杂的联结操作
  • 事务
  • 清晰的扩展模式
  • 既有资源更丰富:开发者、社区、代码库、工具等
  • 通过索引进行查询非常快

选取 NoSQL 的原因:

  • 半结构化数据
  • 动态或灵活的模式
  • 非关系型数据
  • 不需要复杂的联结操作
  • 存储 TB (甚至 PB)级别的数据
  • 高数据密集的工作负载
  • IOPS 高吞吐量

适合 NoSQL 的示例数据:

  • 埋点数据和日志数据
  • 排行榜或者得分数据
  • 临时数据,如购物车
  • 频繁访问的(“热”)表
  • 元数据/查找表

为什么应该使用 NoSQL 数据库?

参考

NoSQL 数据库非常适合许多现代应用程序,例如移动、Web 和游戏等应用程序,它们需要灵活、可扩展、高性能和功能强大的数据库以提供卓越的用户体验。

  • 灵活性:NoSQL 数据库通常提供灵活的架构,以实现更快速、更多的迭代开发。灵活的数据模型使 NoSQL 数据库成为半结构化和非结构化数据的理想之选。
  • 可扩展性:NoSQL 数据库通常被设计为通过使用分布式硬件集群来横向扩展,而不是通过添加昂贵和强大的服务器来纵向扩展。一些云提供商在后台将这些操作处理为完全托管服务。
  • 高性能:NoSQL 数据库针对特定的数据模型和访问模式进行了优化,这与尝试使用关系数据库完成类似功能相比可实现更高的性能。
  • 强大的功能:NoSQL 数据库提供功能强大的 API 和数据类型,专门针对其各自的数据模型而构建。

行式数据库和列式数据库区别

行式数据库:

1.数据是按行存储的

2.没有建立索引的查询将消耗很大的io

3.建立索引和视图需要花费一定的物理空间和时间资源

4.面对大量的查询,复杂的查询,数据库必须被大量膨胀才能满足性能需求

列式数据库:

1.数据是按列存储的,每一列单独存放

2.数据既是索引

3.只访问查询涉及的列,大量降低系统io

4.每一列有一个线程来处理,支持查询的高并发

5.数据类型一致,数据特征相似,高效的压缩

为什么可以大量降低系统io: 复制代码比如查询表中所有人的名字;行式数据库需要查询所有行,列式数据库只需要查询name列.

行式与列式数据库优缺点:

  • 复制代码根据实际的业务场景来选择对应的数据库系统.
  • 传统的crud操作应用适合行式数据库(表之间有关联关系);
  • 列式数据库适用于数据仓库,数据分析,海量存储,涉及到不经常更新的数据库,列式在并行

如果你主要处理的是事务性数据(频繁插入和更新),行存储通常更合适;而如果是大规模的批量分析或查询,列存储将更为高效。

hash分片和range分片

分布式存储系统对数据分区一般有两种方式:Hash 分区和 Range 分区。Hash 分区对每条数据算一个哈希值,映射到一个逻辑分区上,然后通过另外一层映射将逻辑分区映射到具体的机器上,很多数据库中间件、缓存中间件都是这样做的。这种方式的优点是数据写入一般不会出现热点,缺点是原本连续的数据经过 Hash 后散落在不同的分区上变成了无序的,那么,如果需要扫描一个范围的数据,需要把所有的分区都扫描一遍。

相比而言,Range 分区对数据进行范围分区,连续的数据是存储在一起的,可以按需对相邻的分区进行合并,或者中间切一刀将一个分区一分为二。业界典型的系统像 HBase。这种分区方式的缺点是一、对于追加写处理不友好,因为请求都会打到最后一个分片,使得最后一个分片成为瓶颈。优点是更容易处理热点问题,当一个分区过热的时候,可以切分开,迁移到其他的空闲机器上。

从实际业务使用的角度来说,提供数据强一致性能够大大减小业务的负担。另外 Range 分区能够支持更丰富的访问模式,使用起来更加灵活。

Range 分片 主要适用于需要按 row key 范围 存取数据的场景,它能够提供高效的范围查询、负载均衡、存储优化等优点。许多现代分布式数据库,如 HBase、Bigtable、Cassandra、TiKV 和 CockroachDB 等,都采用了这种方式来分割和存储数据。

使用 range 分片的一个最大优势是可以高效地执行 范围查询(range queries)。由于数据是按 row key 范围进行分片的,查询某个 row key 范围的数据时,系统能够直接定位到对应的 Region 或 shard,避免了全表扫描。比如,查询某一时间段的数据,系统只需要查找该时间范围内的 row key,而不是扫描整个数据集。

选型

参考

img

  按照数据存放形态划分,主要分一下3种:

  •  unstructured data 非结构化数据:指的是文件类,包括但不限于音视频、各种文档、日志等,通常存放于各种文件系统File System。
    •  这类数据没有“规则”,适合存放在OS的本地磁盘。
    • 如果有分布式distribute、冗余备份redundant backp等需求,可以考虑HDFS、对象存储cos/oss、Amazon的S3等!
  • structed data 结构化数据: 这类数据非常规整,整齐划一,适合存放在excel类的表格型table数据库中。
  • 常见的关系型数据库有mysql、sql server、Oracle、db2等,支持事务transaction;
  • 大数据类的分布式数据库有hive、pg、mpp等,不支持tramsaction;
  • 简而言之:能存放在excel的数据,也能存放在这些数据库中;
  • 因为增删改查这种规则数据长用的就是SQL语句,所以这类也成为sql数据库
  • semi-structed data 半结构化数据:这类数据相比上一种结构化数据,也是一行一行的,但是没那么规整,主要是KV结构的数据,比如key是uid,value是各种属性,包括但不限于name、age、height、weight、friends等!
  •  key是固定长度的,但是value的长度可变,相比于上面的sql数据库,下面的这种明显扩展性extensibility更好!
  • 平时写代码时,这种结构的数据常用hashmap存储,但hashmap的数据都放在内存memory,一旦断电,数据全丢,为能持久化保存这种KV数据,最终肯定是要存放在硬盘disck上的,所以衍生出了很多著名的KV半结构化数据库: hbase、redis、mongoDB、Cassandra等!因为存放的数据没那么“规整”(毕竟value时可变的嘛),所以又被成为NoSql数据库!

存储考虑点, 对数据库的需求有:

需求是否必须
低延迟必须
支持CP模型必须
支持非结构化数据存储必须
有亿级数据的存储方案必须
有成熟的扩容方案必须
冷热数据非必须

Search

    Table of Contents