【架构设计】15-高性能NoSQL

关系型数据库的缺点

关系型数据库已经非常成熟,但是并不是完美的,仍然有以下缺点:

  • 关系型数据库存储的是行记录,无法存储数据结构。
  • 关系型数据库的Schema扩展非常不方便。

    关系型数据库的Schema是强约束,无法操作不存在的列。当要扩展列时,需要先执行DDL操作。

  • 关系型数据库在大数据场景下I/O较高。
    如果对关系型数据库的表进行统计的时候,I/O会非常的高。即使只是统计几列的数据,它也会把行中所有列的数据加载到内存当中。
  • 关系型数据库的全文搜索功能比较弱。
    关系型数据库的全文搜索只能用Like进行扫描,性能低。

针对这些问题,就诞生了NoSQL。在某些场景不NoSQL的性能会比关系型数据库的性能更好。但是这种性能提升是牺牲了ACID的某些特性。要注意的是NoSQL并不是银弹,它是关系型数据库的补充。NoSQL != No SQL,NoSQL = Not Only SQL。

常见的NoSQL方案分为以下几类:

  • K-V存储:解决关系型数据库无法存储数据结构的问题,如Redis。
  • 文档型数据库:解决关系型数据库强Schema的问题,如MongoDB。
  • 列式数据库:解决大数据场景下I/O较高的问题,如HBASE。
  • 全文搜索引擎:解决关系型数据库全文搜索功能弱的问题,如ES。

下面分别介绍:

K-V存储

K-V存储全称是key-value存储,其中key是数据标识,Value是数据。以Redis为代表,是开源的高性能K-V缓存和存储系统。其Value存储的数据可以是具体数据结构,包括String,Map,List,Set等等。
Redis的缺点在于不支持完整的ACID事务。Redis只保证了事物的隔离性和一致性,无法保证原子性和持久性。

文档型数据库

文档型数据库最大的特点就是No Schema,可以存储和读取任意数据。目前大部分文档型数据库数据存储都是使用JSON,因为JSON是自描述的,无须使用之前定义的字段。读取一个JSON中不存在的字段也不会报报错。

文档型数据库的优势在于:

  • 新增字段简单
    业务增加字段不需要你像关系型数据库那样进行DDL操作,直接在数据上增加字段即可。
  • 历史数据不会出错
    即使新增了字段,读取历史数据也不会报错,对于新增的字段也只会返回空。
  • 可以存储复杂的数据结构
    因为使用JSON作为数据结构,所以可以描述很复杂的数据结构。

文档型数据库的缺点在于:

  • 不支持事务。
  • 不支持Join操作。

列式数据库

列式数据库是指按照列来存储数据,有别于关系型数据库按照行来存储数据。

关系型数据库使用行式存储的优点在于:

  • 业务同时读取多个列时效率高,因为这些列是按行存储在一起的,一次行操作可以把多个列的值读取到磁盘上面。
  • 能够一次性完成对一行数据多个列的写操作。保证了行数据的原子性和一致性。因为这些数据都是写在一起的。如果是采用列式存储的,因为一行的数据存储在不同的文件上,所以可能导致某些列更新成功,某些列更新失败,导致数据不一致。

但是,如果在海量数据的情况下,比如我们需要查询用户年龄这个字段,如果是行式存储的话,需要把用户的所有数据放到内存中,然后返回用户年龄这个字段的值。但是采用列式存储的话,只需要读取年龄这个字段的值即可。可以大大的减少I/O数量。

另一个方面,可以提供更高的压缩比。因为某列的数据类型都是一致的,能够提高更高的压缩比。普通的行式存储的压缩比在3:1到5:1左右。列式存储的压缩比在8:1和30:1左右。

全文搜索引擎

传统的关系型数据库一般采用索引的方式来提高访问速度,但是在全文搜索的业务场景下,索引也无能为力,主要在:

  • 全文搜索的条件可以任意的组合,如果都加上索引的话,索引的数量会非常的多。
  • 全文搜索的模糊匹配方式,索引无法满足,只能用like实现,需要全文扫描。

全文搜索的基本原理

全文搜索引擎的技术原理被称为“倒排索引”。也常被称为反向索引、置入档案或反向档案,是一种索引方法,其基本原理是建立单词到文档的索引。之所以称为“倒排”,是和“正排”索引相对的,“正排”索引的基本原理是建立文档到单词的索引。下面用一个例子来说明“倒排”和“正排”。

假设我们有一个文章列表,用户可以浏览文章和搜索文章。

正排索引示例:

文章ID 文章名称 文章内容
1 敏捷架构 文档包含:架构、设计、架构师等词
2 Java编程必知 Java、编辑、面向对象、架构、设计等词
3 面向对象 设计、模式、对象、类、Java等词

正排索引用于根据文档名称来查询文档内容,当用户点击文章名称“Java编程必知”时,查询文章内容展现给用户。

倒排索引示例:
| 单词 | 文档ID |
| —— | :———-:|
|架构 |1,2 |
|设计 |1,2,3 |
|Java |2,3 |

::: warning 注意
示例只写了三个索引,实际上每一个单词就会有一个索引。
:::

倒排索引适用于根据关键字查询文档内容。例如,用户想看“设计”相关的内容,需要把文档内容包含设计的所有内容返回给用户。

全文搜索的使用方式

全文搜索的索引对象是单词和文档,而关系型数据库的索引对象是键和行。为了让全文搜索引擎支持关系型数据的全文搜索,需要将关系型数据转换成文档。

目前常见的转换方式是将关系型数据按照对象的形式转换成JSON文档,然后将JSON文档输入全文搜索引擎进行索引。

全文搜索引擎能够基于JSON文档建立全文索引,然后快速进行全文搜索。以ES为例,其索引的基本原理是:

  • ES是分布式的文档存储方式。它能存储和检索复杂的数据结构–序列化成JSON文档–以实时的方式。
  • 在ES里面,每个字段的所有数据是默认被索引的。即每个字段都有为了快速检索设置的专用倒排索引。而且,它能在相同的查询中使用所有倒排索引,并以惊人的速度返回结果。

   转载规则


《【架构设计】15-高性能NoSQL》 孤独如梦 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
【架构设计】16-高性能缓存 【架构设计】16-高性能缓存
前言虽然我们可以通过很多方式增加存储系统的性能,但某些场景下,只通过存储系统提升性能是不够的: 需要通过复杂的运算得出结果的数据 读多写少的数据:比如明星微博,只要一次Insert,但是却可能需要几千万次的select,对数据库的压力很大
2019-05-29
下一篇 
【架构设计】13-高性能数据库集群:读写分离 【架构设计】13-高性能数据库集群:读写分离
前言读写分离就是将数据库的读写操作分配到不同的机器,原理图如下: 读写分离的基本实现: 数据库服务器搭建集群模式,一主一从或一主多从。 数据库主机负责写,数据库从机负责读。 数据库主机通过复制将数据同步到从机,每个数据库服务器都保存所有的
2019-05-29
  目录