ES的核心是倒排索引。
就是一个词term被什么文档所包含。
term -> documents(posting list)
这些数据存储在磁盘上。
以上是最基础的版本。
倒排索引虽然很快,但是空间消耗很大。
需要优化
- 保证搜索速度更快(优势更明显)
- 空间占用减小(缺点缩小)
ES的优化设计
ES对性能和空间节省做了大量的优化。
搜索速度优化
数据按规律排序存储
将全部数据按一定规则(Term的前缀)拆分到不同的磁盘Block中。
使用一种快速算法可以快速定位到这个term所在的磁盘Block。
这种算法就是FST(Finite State Transducers)。
将所有Term做成FST(实际是取到能区分磁盘Block的前缀部分即可)
磁盘空间优化
Term Dictionary的磁盘空间优化
由于Term词典是采用前缀规律组织起来的,因此,一个Block内的Term一定有一段相同的前缀。
Term词典只需要存储差异化的后缀即可,从而节省存储空间。
Posting Lists (文档ID)的磁盘空间优化
采用整形数id
这个文档ID和ES索引里的唯一_id 不一样。
ES索引里的_id可以是string类型,压缩率不高。
(segment是存储文档的最小组织单元,可以存储2^32个文档。里面的id是唯一的整形数id。以便于被高效压缩)
id采用delta-encoding编码
- id是排序的。
- 采用增量编码(delta-encoding)对id的存储空间进行压缩。
原输入[id1, id2, id3...]
delta-encodinig: [id1, id2-id1, id3-id2]
由于是相对值,实际每个值会相比原来更小(例如,如果所有值都小于255,则每个只需要1个字节进行存储。原来 4 bytes * len(list) -> 现在 1 byte * len(list))
3 Frame of Reference
上面可以发现,如果一个相对值比较大(瓶颈),则会导致整体都必须按这个最大值的类型进行存储。
这里采用分而治之,减少这种瓶颈带来的波及。
将所有id分为多个block,每个block最大256个ids。
计算每个block最大需要多少bit来存储,将这个值写到block的开头(这个header采用1个字节存储即可)
相比只用delta-encoding,delta值(相对值)从字节(Byte)单位精细到比特(Bit)单位。
整体流程
从优化前的24字节降为仅需7字节。