倒排索引的存储结构可以参考图9。其中词典是存放的内存里的,词典就是整个文档集合中解析出的所有单词的列表集合;每个单词又指向了其对应的倒排列表,倒排列表的集合组成了倒排文件,倒排文件存放在磁盘上,其中的倒排列表内记录了对应单词在文档中信息,即前面提到的词频、位置等信息。
下面以一个具体的例子来描述下,如何从一个文档集合中生成倒排索引。
如图10,共存在5个文档,第一列为文档编号,第二列为文档的文本内容。
将上述文档集合进行分词解析,其中发现的10个单词为:[谷歌,地图,之父,跳槽,Facebook,加盟,创始人,拉斯,离开,与],以第一个单词”谷歌“为例:首先为其赋予一个唯一标识 ”单词ID“, 值为1,统计出文档频率为5,即5个文档都有出现,除了在第3个文档中出现2次外,其余文档都出现一次,于是就有了图11所示的倒排索引。
1.4.1 单词词典查询优化对于一个规模很大的文档集合来说,可能包含几十万甚至上百万的不同单词,能否快速定位某个单词,这直接影响搜索时的响应速度,其中的优化方案就是为单词词典建立索引,有以下几种方案可供参考:
词典Hash索引
Hash索引简单直接,查询某个单词,通过计算哈希函数,如果哈希表命中则表示存在该数据,否则直接返回空就可以;适合于完全匹配,等值查询。如图12,相同hash值的单词会放在一个冲突表中。
词典BTREE索引
类似于Innodb的二级索引,将单词按照一定的规则排序,生成一个BTree索引,数据节点为指向倒排索引的指针。
二分查找
同样将单词按照一定的规则排序,建立一个有序单词数组,在查找时使用二分查找法;二分查找法可以映射为一个有序平衡二叉树,如图14这样的结构。
FST(Finite State Transducers )实现
FST为一种有限状态转移机,FST有两个优点:1)空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;2)查询速度快。O(len(str))的查询时间复杂度。
以插入“cat”、 “deep”、 “do”、 “dog” 、“dogs”这5个单词为例构建FST(注:必须已排序)。
如图15 最终我们得到了如上一个有向无环图。利用该结构可以很方便的进行查询,如给定一个词 “dog”,我们可以通过上述结构很方便的查询存不存在,甚至我们在构建过程中可以将单词与某一数字、单词进行关联,从而实现key-value的映射。
当然还有其他的优化方式,如使用Skip List、Trie、Double Array Trie等结构进行优化,不再一一赘述。
二、ElasticSearch使用心得下面结合贷前系统具体的使用案例,介绍ES的一些心得总结。
2.1 概况目前使用的ES版本:5.6
官网地址:https://www.elastic.co/products/elasticsearch
ES一句话介绍:The Heart of the Elastic Stack(摘自官网)
ES的一些关键信息:
2010年2月首次发布
Elasticsearch Store, Search, and Analyze
丰富的Restful接口
2.2 基本概念索引(index)
ES的索引,也就是Index,和前面提到的索引并不是一个概念,这里是指所有文档的集合,可以类比为RDB中的一个数据库。
文档(document)
即写入ES的一条记录,一般是JSON形式的。
映射(Mapping)
文档数据结构的元数据描述,一般是JSON schema形式,可动态生成或提前预定义。
类型(type)
由于理解和使用上的错误,type已不推荐使用,目前我们使用的ES中一个索引只建立了一个默认type。
节点
一个ES的服务实例,称为一个服务节点。为了实现数据的安全可靠,并且提高数据的查询性能,ES一般采用集群模式进行部署。
集群
多个ES节点相互通信,共同分担数据的存储及查询,这样就构成了一个集群。
分片
分片主要是为解决大量数据的存储,将数据分割为若干部分,分片一般是均匀分布在各ES节点上的。需要注意:分片数量无法修改。
副本
分片数据的一份完全的复制,一般一个分片会有一个副本,副本可以提供数据查询,集群环境下可以提高查询性能。
2.3 安装部署
JDK版本: JDK1.8
安装过程比较简单,可参考官网:下载安装包 -> 解压 -> 运行
安装过程遇到的坑:
ES启动占用的系统资源比较多,需要调整诸如文件句柄数、线程数、内存等系统参数,可参考下面的文档。
2.4 实例讲解下面以一些具体的操作介绍ES的使用:
2.4.1 初始化索引