目录
ES——elasticsearch
全文检索引入ES——倒排索引
应用场景:海量数据情况下的搜索。
什么是索引?索引的本质
空间换时间
帮助快速检索
以数据结构为载体(mysql以b+树为数据结构)
以文件的形式落地
为什么es比mysql适合做搜索?
mysql在超过百万千万数据量的情况下,搜索性能堪忧
mysql的索引数据结构:B+树,当层级越来越深的时候,性能也会下降。
单个node节点的体积越小,一层相对来说可以装更多个节点。
当以ID为索引的时候,确实如此。但是如果以文本(类似于文章的内容详情content)作为索引,它的大小必不可能小。性能也就下去了。
倒排索引的建立过程:
1切词:把一句话切成一个一个词
2规范化:类似于去掉am这样的无用词,do和Doing直接划分为Do
3去重:顾名思义
4字典序:排的是id,放的是int数组
倒排索引数据结构FST*
term index(加速) -- term dictionary(词项) – posting list(倒排表 ID int数组)
搜索引擎三个要点:快,准确(相关度),召回率
相关度(准确度)的计算两种算法: BM25和TF-IDF 相关度评分算法
召回率:返回数据的丰富性。随便搜索一点都能搜索出来
问题: posting list倒排表如果有特别多的id怎么办?怎么去做存储?
做压缩,而不是直接去使用Int数组存储。压缩算法两个:for和rbm算法
倒排索引的压缩算法(FOR RBM)
1.FOR压缩算法(Frame Of Reference )
考虑把每个数字,只存储和前一个的差值。采用自定义类型bit位来存储
例如说
[1,2,3….100w] à [1,1,1,1,1…1]
存储空间: 100w*32bit=4MB -> 100w bit =0.125MB 压缩了32倍(最高压缩倍数)
当然上面这个是极端例子.看以下例子
[73,300,302,332,343,372] -> [73,227,2,30,11,29]
6*32bit=24Bytes à 6*8bit= 1B+48bit =7Bytes (再切分)
问题来了;为什么不直接每个数字分配一个自定义的数据类型呢?
原因:
自定义数据类型的话,也是会占空间的(1bit)当定义的类型多了,也会造成空间浪费。
2.RBM压缩算法(Roaring bitmaps)
为啥要那么多算法?
因为FOR压缩算法只适应于数字范围较小的时候可以用。(稠密数组)
如果是稀疏数组,那么就可以用RBM压缩算法。
考虑当倒排表posting list为这样的一个数组:
[1000,62101,131385,132052,191173,196658]
显然此时数字之间的差值已经很大了,如果此时仍然采用FOR压缩算法的话,那么它将变成[1000,61101,69284,665,59121,5485] 此时为每个数去做自定义类型的话,其实作用已经不大了。
用RBM算法的做法是这样的:
1.对每个数字除以65536,也就是2^16.分别得到商和余数
[0,1000] [0,62101] [2,313] [2,980] [2,60101] [3,50]
为什么要选择65536,因为它是2^16,而我们的int类型是2^32,也就是说,任何一个int数字,除以65536得到的商和余数都不会超过65535.因为它事实上是可以拆分成2^16*2^16
2.此时我们得到了商和余数之后,其实就得到了键值对,即商和余数的键值对
键为商,值为余数
存放键的容器是一个short类型的数组. short[]
存放后面的值的容器就是container.
查看源码发现有三种container:
ArrayContainer
BitmapContainer
RunContaine
其实就是short类型的数组.可以计算一下:每个数占用2个Byte大小,当容器达到4096个时,就占用了4096*2=8182Byte=8KB,最大是65536个占用65536*2/1024=128KB
以值的个数为横坐标,占用空间大小为纵坐标可以画成一张曲线图:
采用Bitmap为数据结构:
举例:
Bitmap表示一个数为6的话就是这样的
Bitmap表示一个数为65535的话是这样
也就是说,以它的bit位下标为1时就表示哪个数字
那么由于我们的值列表里面存放的数字不会超过65536个,并且大小也不会超过65536
我们只要使用一个有65536bit位的bitmap就可以存放所有值,它产生的效果是下面折线图的红色线
此时可以发现,采用bitmapContainer时,不论有多少个值,占用的空间大小都是65536bit/8/1024=8KB
考虑这样一个数组:
[1,2,3,…100W]
这是一个连续的有100W个数字的数组,在这种情况下,可以采用[1,100W]两个数字来表示这个数组。此时它的占用空间压缩倍数达到了100W: 2 = 50W : 1
但是这种的局限性会比较小,要求是连续性较高的数组。
本文同步更新于个人博客:浅谈ES以及索引的本质 - 文章 - 巅峰永无止境 (markyao.top)