文章复制于http://www.noobyard.com/article/p-gjijfnuo-go.html,感谢分享,做为学习记录。
KV型NoSql(代表----Redis)
KV型NoSql顾名思义就是以键值对形式存储的非关系型数据库,是最简单、最容易理解也是大家最熟悉的一种NoSql,因此比较快地带过。Redis、MemCache是其中的代表,Redis又是KV型NoSql中应用最广泛的NoSql,KV型数据库以Redis为例,最大的优点我总结下来就两点:
因此,KV型NoSql最大的优点就是高性能,利用Redis自带的BenchMark做基准测试,TPS可达到10万的级别,性能非常强劲。同样的Redis也有所有KV型NoSql都有的比较明显的缺点:
综上所述,KV型NoSql最合适的场景就是缓存的场景:
例如根据用户id查询用户信息,每次根据用户id去缓存中查询一把,查到数据直接返回,查不到去关系型数据库里面根据id查询一把数据写到缓存中去。
搜索型NoSql(代表----ElasticSearch)
传统关系型数据库主要通过索引来达到快速查询的目的,但是在全文搜索的场景下,索引是无能为力的,like查询一来无法满足所有模糊匹配需求,二来使用限制太大且使用不当容易造成慢查询,搜索型NoSql的诞生正是为了解决关系型数据库全文搜索能力较弱的问题,ElasticSearch是搜索型NoSql的代表产品。
全文搜索的原理是倒排索引,我们看一下什么是倒排索引。要说倒排索引我们先看下什么是正排索引,传统的正排索引是文档-->关键字的映射,例如"Tom is my friend"这句话,会将其切分为"Tom"、"is"、"my"、"friend"四个单词,在搜索的时候对文档进行扫描,符合条件的查出来。这种方式原理非常简单,但是由于其检索效率太低,基本没什么实用价值。
倒排索引则完全相反,它是关键字-->文档的映射,我用张表格展示一下就比较清楚了:
意思是我现在这里有四个短句:
搜索引擎会根据一定的切分规则将这句话切成N个关键字,并以关键字的维度维护关键字在每个文本中的出现次数。这样下次搜索"Tom"的时候,由于Tom这个词语在"Tom is Tom"、"Tom is my friend"、"Tom is Betty's husband"三句话中都有出现,因此这三条记录都会被检索出来,且由于"Tom is Tom"这句话中"Tom"出现了2次,因此这条记录对"Tom"这个单词的匹配度最高,最先展示。这就是搜索引擎倒排索引的基本原理,假设某个关键字在某个文档中出现,那么倒排索引中有两部分内容:
可以举一反三,我们搜索"Betty Tom"这两个词语也是一样,搜索引擎将"Betty Tom"切分为"Tom"、"Betty"两个单词,根据开发者指定的满足率,比如满足率=50%,那么只要记录中出现了两个单词之一的记录都会被检索出来,再按照匹配度进行展示。
搜索型NoSql以ElasticSearch为例,它的优点为:
同样,ElasticSearch也有比较明显的缺点:
因此,搜索型NoSql最适用的场景就是有条件搜索尤其是全文搜索的场景,作为关系型数据库的一种替代方案。
另外,搜索型数据库还有一种特别重要的应用场景。我们可以想,一旦对数据库做了分库分表后,原来可以在单表中做的聚合操作、统计操作是否统统失效?例如我把订单表分16个库,1024张表,那么订单数据就散落在1024张表中,我想要统计昨天浙江省单笔成交金额最高的订单是哪笔如何做?我想要把昨天的所有订单按照时间排序分页展示如何做?这就是搜索型NoSql的另一大作用了,我们可以把分表之后的数据统一打在搜索型NoSql中,利用搜索型NoSql的搜索与聚合能力完成对全量数据的查询。
至于为什么把它放在KV型NoSql后面作为第二个写呢,因为通常搜索型NoSql也会作为一层前置缓存,来对关系型数据库进行保护。
列式NoSql(代表----HBase)
列式NoSql,大数据时代最具代表性的技术之一了,以HBase为代表。
列式NoSql是基于列式存储的,那么什么是列式存储呢,列式NoSql和关系型数据库一样都有主键的概念,区别在于关系型数据库是按照行组织的数据:
看到每行有name、phone、address三个字段,这是行式存储的方式,且可以观察id = 2的这条数据,即使phone字段没有,它也是占空间的。
列式存储完全是另一种方式,它是按每一列进行组织的数据:
这么做有什么好处呢?大致有以下几点:
第二点说到了数据压缩,什么意思呢,以比较常见的字典表压缩方式举例:
自己看图理解一下,应该就懂了。
接着继续讲讲优缺点,列式NoSql,以HBase为代表的,优点为:
说了这么多HBase的优点,又到了说HBase缺点的时候了:
因此HBase比较适用于那种KV型的且未来无法预估数据增长量的场景,另外HBase使用还是需要一定的经验,主要体现在RowKey的设计上。
文档型NoSql(代表----MongoDB)
坦白讲,根据我的工作经历,文档型NoSql我只有比较浅的使用经验,因此这部分只能结合之前的使用与网上的文章大致给大家介绍一下。
什么是文档型NoSql呢,文档型NoSql指的是将半结构化数据存储为文档的一种NoSql,文档型NoSql通常以JSON或者XML格式存储数据,因此文档型NoSql是没有Schema的,由于没有Schema的特性,我们可以随意地存储与读取数据,因此文档型NoSql的出现是解决关系型数据库表结构扩展不方便的问题的。
MongoDB是文档型NoSql的代表产品,同时也是所有NoSql产品中的明星产品之一,因此这里以MongoDB为例。按我的理解,作为文档型NoSql,MongoDB是一款完全和关系型数据库对标的产品,就我们从存储上来看:
看到,关系型数据库是按部就班地每个字段一列存,在MongDB里面就是一个JSON字符串存储。关系型数据可以为name、phone建立索引,MongoDB使用createIndex命令一样可以为列建立索引,建立索引之后可以大大提升查询效率。其他方面而言,就大的基本概念,二者之间基本也是类似的:
因此,对于MongDB,我们只要理解成一个Free-Schema的关系型数据库就完事了,它的优缺点比较一目了然,优点:
缺点在于:
总而言之,MongDB的使用场景很大程度上可以对标关系型数据库,但是比较适合处理那些没有join、没有强一致性要求且表Schema会常变化的数据。
总结:数据库与NoSql及各种NoSql间的对比
最后一部分,做一个总结,本文归根到底是两个话题:
首先是第一个话题,关系型数据库与非关系型数据库的选择,在我理解里面无非就是两点考虑:
第一点,不多解释应该都理解,非关系型数据库都是通过牺牲了ACID特性来获取更高的性能的,假设两张表之间有比较强的一致性需求,那么这类数据是不适合放在非关系型数据库中的。
第二点,核心数据不走非关系型数据库,例如用户表、订单表,但是这有一个前提,就是这一类核心数据会有多种查询模式,例如用户表有ABCD四个字段,可能根据AB查,可能根据AC查,可能根据D查,假设核心数据,但是就是个KV形式,比如用户的聊天记录,那么HBase一存就完事了。
这几年的工作经验来看,非核心数据尤其是日志、流水一类中间数据千万不要写在关系型数据库中,这一类数据通常有两个特点:
一旦使用关系型数据库作为存储引擎,将大大降低关系型数据库的能力,正常读写QPS不高的核心服务会受这一类数据读写的拖累。
接着是第二个问题,如果我们使用非关系型数据库作为存储引擎,那么如何选型?其实上面的文章基本都写了,这里只是做一个总结(所有的缺点都不会体现事务这个点,因为这是所有NoSql相比关系型数据库共有的一个问题):
但是这里特别说明,选型一定要结合实际情况而不是照本宣科,比如:
所以,如果不考虑实际情况,虽然合适有些存储引擎更加合适,但是强行使用反而适得其反,总而言之,适合自己的才是最好的。