多角度分析NoSQL和RDBMS

在日常的学习开发中,越来越感觉到技术选型的重要性,在这其中,数据库选择占了很大一部分。针对不同的需求场景去选择适合的数据库(关系型or非关系型)就是一个重要的能力了,一直都有听说NoSQL如何如何完爆关系型数据库,真的有那么神奇吗?下面就各类取一个典型,简单分析一下。

关系型数据库的一些缺陷

  • 不支持存储数据结构,比如想使用接近Java集合框架的特性是不能直接通过它做到的。
  • 扩展性不够好,一旦在迭代过程中有需求要增删改字段,就需要执行修改表结构的语句,而修改期间表是被加锁的,会需要暂停服务。

  • 大数据场景下IO过高,因为关系型数据库采取的是“按行存储”,而大数据处理中很多时候需要的反而是很长一段的单列数据,但是关系型数据库还需要按行把整行数据读取到内存中。

  • 全文检索功能残缺。并不是说不可以使用,只是不建议也不应该使用关系型数据库做全文检索,性能较差。
  • 大并发场景的表现不够好,需要开发人员精细地控制锁粒度。

K-V数据库

KV数据库里应用最多的就是Redis了,我们知道在实际场景中它更多的被用于内容缓存、访问负载大的场景、Session分离、排行榜、点赞功能,购物车等等。最主要的优点就在于性能,大约可以支持10W左右的TPS(Transactions per second),支持众多的数据结构,比如Hash,SortedSet,Bitmap,Hyperlog等等。

但是就Redis来说,事务上的ACID特性就不能得到保证了,主要就是A,原子性。Redis是单线程模型,但Redis的普通操作是原子性的,只是Redis事务不支持回滚。也就是说,涉及到一个以上的键去关联数据和需要严格事务支持的场景,是不能选择Redis的。

文档式数据库

我自己接触过比较典型的是MongoDB。首先在MongoDB中存储的数据是以JSON的行形势展现,JSON本身是一个可读的强大的描述语言。主要就是解决了关系型数据库在表结构不明确的场景下的无奈。就比如说我们经常会需要的在线填写用户信息,就比如一些职场类网站的个人信息,有很多必填项和选填项且用户可以定制自己的额外信息,在这种场景下,固定的表结构就不好解决这个问题,这也正是文档式数据库的用武之地(当然,你也可以在一个字段里面放一个复杂的JSON,相当于在MySQL里面套了一个文档数据库,解析的性能损耗不言而喻了。)

优点有:字段更改方便,对旧数据兼容,从代码层面处理判空即可,存储信息结构更灵活。缺点也比较明显,如果业务中大量需要多条数据之间的关联查询,单靠MongoDB就不够了。它对于多条数据事务可以说是不支持的。拿ACID来说,事务仅在单文档中保证原子性,且不支持像我们在MySQL那样复杂的join查询。

全文搜索引擎

ElasticSearch应该就是最受欢迎的企业搜索引擎了。它是一个可扩展、开源的全文搜索分析引擎。几乎能实时地进行对大量数据的存储、搜索和分析。海量数据查询的场景就很多了,论坛搜索文章,电商搜索商品都会用到,并且将数据存入ElasticSearch中可以很方便的进行聚合和数据分析的工作。生产上采用的ElasticSearch集群保证了极大的数据容量和可扩展性,是代替关系型数据库全文检索功能的良好解决方案。

最主要的优势就是全文检索的高性能,这个优势的原理是基于“倒排索引”,关于它的介绍之后会单独写一篇文章来详细分析。

列式数据库

HBase是大数据上广泛应用的列式数据库,基于HDFS文件系统,并参考了BigTable文档模型。

它有着很高的存储空间利用率。首先我们可以知道,传统关系型数据库是按行存储的,一行数据各个字段的数据类型一般都会有不同。列式数据库对不同列各自的类型的特征而选择特定的压缩算法使得它有更高的压缩率。普通行式数据库压缩率大概在1/5-1/3左右,列式数据库的压缩率大概在1/30-1/8左右(常用的方式就是字典表压缩)。

在大数据场景需要对一列进行读取时,列式数据库的性能是远远高于行式的,因为一列数据是存储在一起的,一次磁盘IO可以将整列都读取到内存中。

和其它非关系型数据库一样,对于多行数据,它同样不支持多行事务的原子性,也保证不了多行的一致性。且由于按列读取的操作,也不适合频繁的少量行数据读取,不适合做更新和删除的实时操作。