抛砖引玉:我们先来思考一个问题,es中的 agg 桶聚类,等操作是如何来做到的?
如果想要提升聚类的性能,又应该如何做呢?
我们可以从 es的底层存储原理中来寻找答案!所以将会学到 Doc Values这个列式存储的数据结构。
那又为什么需要列式存储? 我提一个需求你大概就能明白了:如果mysql中数据有1000W,如果让你去执行group by操作,需要多长的时间呢? 假如数据有 1 亿、10亿,又需要花多长时间呢?如果能做到秒级别? 因为mysql是按行来存储数据的,想要完成这个操作,就得一条一条数据读出来,然后再去计算分组。而列存就不一样了。只需要读出来我们需要 group by的字段即可。
Doc Values
- Doc Values 数据结构能够解决聚类(group by)的问题
- Doc Values 数据结构能够解决 排序的问题
那么doc value究竟是什么呢?
Doc Values 正排索引
Doc Values 定义
在 Elasticsearch 中,Doc Values 就是一种列式存储结构,默认情况下每个字段的 Doc Values 都是激活的(除了 text 类型),Doc Values 是在索引时创建的,当字段索引时,Elasticsearch 为了能够快速检索,会把字段的值加入倒排索引中,同时它也会存储该字段的 Doc Values。
区别于倒排索引的定义,Doc Values 被定义为:“正排索引”。
Doc Values 示例
仍然 以 1.2 文档为例,Doc Values 结构如下所示(仅做举例):
Doc |
Terms |
---|---|
Doc_1 |
brown, dog, fox, jumped, lazy, over, quick, the |
Doc_2 |
brown, dogs, foxes, in, lazy, leap, over, quick, summer |
Doc values 通过转置两者间的关系来解决适用倒排索引聚合效率低、难以扩展的问题。
对比可以看出:倒排索引将词项映射到包含它们的文档,doc values 将文档映射到它们包含的词项。
Doc Values 特点
- 在索引时创建
- 序列化到磁盘
- 适合排序操作
- 将单个字段的所有值一起存储在单个数据列中
- 默认情况下,除text之外的所有字段类型均启用 Doc Values。
Doc Values 适用场景
Elasticsearch 中的 Doc Values 常被应用到以下场景:
- 对一个字段进行排序
- 对一个字段进行聚合
- 某些过滤,比如地理位置过滤
- 某些与字段相关的脚本计算
注意:
因为文档值被序列化到磁盘,我们可以依靠操作系统的帮助来快速访问。
- 当 工作集(working set) 远小于节点的可用内存,系统会自动将所有的文档值保存在内存中,使得其读写十分高速;
- 当其远大于可用内存,操作系统会自动把 Doc Values 加载到系统的页缓存中,从而避免了 jvm 堆内存溢出异常。
Doc Values 使用注意事项
对于不需要:排序、聚合、脚本计算、地理位置过滤的业务场景,可以考虑禁用:Doc Values,以节约存储。
PUT my_index
{
"mappings": {
"properties": {
"title": {
"type": "keyword",
"doc_values": false
}
}
}
}