浅谈ES以及索引的本质

目录

ES——elasticsearch

全文检索引入ES——倒排索引


ES——elasticsearch

应用场景:海量数据情况下的搜索。

什么是索引?索引的本质

空间换时间

帮助快速检索

以数据结构为载体(mysql以b+树为数据结构)

以文件的形式落地

为什么es比mysql适合做搜索?

mysql在超过百万千万数据量的情况下,搜索性能堪忧

mysql的索引数据结构:B+树,当层级越来越深的时候,性能也会下降。

单个node节点的体积越小,一层相对来说可以装更多个节点。

当以ID为索引的时候,确实如此。但是如果以文本(类似于文章的内容详情content)作为索引,它的大小必不可能小。性能也就下去了。

全文检索引入ES——倒排索引

倒排索引的建立过程:

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 (再切分)

  • [73,227] ,[2,30,11,29]  =1B+ 8bit*2 +1B+5bit*4=3B+4B=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

  1. ArrayContainer

其实就是short类型的数组.可以计算一下:每个数占用2个Byte大小,当容器达到4096个时,就占用了4096*2=8182Byte=8KB,最大是65536个占用65536*2/1024=128KB

以值的个数为横坐标,占用空间大小为纵坐标可以画成一张曲线图:

 

 

  1. BitmapContainer

采用Bitmap为数据结构:

举例:

Bitmap表示一个数为6的话就是这样的

 

Bitmap表示一个数为65535的话是这样

 

也就是说,以它的bit位下标为1时就表示哪个数字

那么由于我们的值列表里面存放的数字不会超过65536个,并且大小也不会超过65536

我们只要使用一个有65536bit位的bitmap就可以存放所有值,它产生的效果是下面折线图的红色线

 

此时可以发现,采用bitmapContainer时,不论有多少个值,占用的空间大小都是65536bit/8/1024=8KB

  1. RunContainer

考虑这样一个数组:

[1,2,3,…100W]

这是一个连续的有100W个数字的数组,在这种情况下,可以采用[1,100W]两个数字来表示这个数组。此时它的占用空间压缩倍数达到了100W: 2 = 50W : 1

但是这种的局限性会比较小,要求是连续性较高的数组。


本文同步更新于个人博客:浅谈ES以及索引的本质 - 文章 - 巅峰永无止境 (markyao.top)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值