# 倒排和正排索引
## 1\. 正排(doc value)与倒排
> 搜索的时候,要依靠倒排索引;排序的时候,需要依靠正排索引,看到每个document的每个field,然后进行排序,所谓的正排索引,其实就是doc values
> 在建立索引的时候,一方面会建立倒排索引,以供搜索用;一方面会建立正排索引,也就是doc values,以供排序,聚合,过滤等操作使用
> 正排索引:
>
> 1. 如果你的某个field设置为不分词,那么在建立索引的时候(index-time),就会自动生成doc value
> 2. doc value(正排索引):
> 是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中,性能还是会很高;如果内存不足够,os会将其写入磁盘上
~~~
doc1: hello world you and me
doc2: hi, world, how are you
~~~
> 倒排索引:数据-文档的二维矩阵
~~~
word doc1 doc2
hello *
world * *
you * *
and *
me *
hi *
how *
are *
~~~
> 例如搜索hello you,搜索语句会按照index中对应的field的分词器进行分词
> hello you --> hello, you
~~~
hello --> doc1
you --> doc1,doc2
~~~
~~~
doc1: hello world you and me
doc2: hi, world, how are you
~~~
> 正排索引
~~~
doc1: { "name": "jack", "age": 27 }
doc2: { "name": "tom", "age": 30 }
~~~
> 文档-数据的二维矩阵
~~~
document name age
doc1 jack 27
doc2 tom 30
~~~
> 例如通过age排序,方便排序
## 2\. 对于分词的field进行聚合
* 正常情况下,是不可以对分词的field进行聚合的
~~~
PUT myindex/test/1
{
"name":"dailin"
}
~~~
聚合测试
~~~
GET myindex/_search
{
"size": 0,
"aggs": {
"groupby_name": {
"terms": {
"field": "name"
}
}
}
}
~~~
报错
~~~
"reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
~~~
Fielddata默认是关闭的,必须要打开fielddata,然后将正排索引数据加载到内存中,才可以对分词的field执行聚合操作,而且会消耗很大的内存。
如果对分词的field进行聚合,有以下几种方法
1. 对应field的Fielddata设置成true
首先设置mapping
~~~
POST myindex/_mapping/test
{
"properties": {
"name":{
"type": "text",
"fielddata": true
}
}
}
~~~
再次聚合
~~~
GET myindex/_search
{
"size": 0,
"aggs": {
"groupby_name": {
"terms": {
"field": "name"
}
}
}
}
~~~
成功
~~~
"aggregations": {
"groupby_name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "dailin",
"doc_count": 1
}
]
}
}
}
~~~
2. 使用分词field的keyword子field
5.X版本以后,es默认会为每个textfield生成一个keyword(不分词),我们可以利用这个field聚合
* 查看mapping
`GET myindex/_mapping`
~~~
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword", # 生成一个不分词的子field
"ignore_above": 256
}
}
~~~
* 聚合测试
~~~
GET myindex/_search
{
"size": 0,
"aggs": {
"groupby_name": {
"terms": {
"field": "name.keyword"
}
}
}
}
~~~
同样得到一样的结果
> 1. 如果一定要对分词的field执行聚合,那么必须将fielddata=true,然后es就会在执行聚合操作的时候,现场将field对应的数据,建立一份fielddata正排索引,fielddata正排索引的结构跟doc value是类似的,但是只会讲fielddata正排索引加载到内存中来,然后基于内存中的fielddata正排索引执行分词field的聚合操作
> 2. fielddata加载到内存的过程是lazy加载的,对一个analzyed field执行聚合时,才会加载,而且是field-level加载的一个index的一个field,所有doc都会被加载,而不是少数doc不是index-time创建,是query-time创建
> 3. 监控fielddata内存使用
~~~
# 各个分片的fiedata内存占用情况
GET /_stats/fielddata?fields=*
# 各个node的fielddata的内存占用情况
GET /_nodes/stats/indices/fielddata?fields=*
GET /_nodes/stats/indices/fielddata?level=indices&fields=*
~~~
> 4. circuit breaker(fielddata内存使用控制)
~~~
如果一次query load的feilddata超过总内存,就会oom --> 内存溢出
circuit breaker会估算query要加载的fielddata大小,如果超出总内存,就短路,query直接失败
indices.breaker.fielddata.limit:fielddata的内存限制,默认60%
indices.breaker.request.limit:执行聚合的内存限制,默认40%
indices.breaker.total.limit:综合上面两个,限制在70%以内
~~~
### fielddata预加载
如果真的要对分词的field执行聚合,那么每次都在query-time现场生产fielddata并加载到内存中来,速度可能会比较慢
我们是不是可以预先生成加载fielddata到内存中来???
1. fielddata预加载
~~~
POST /test_index/_mapping/test_type
{
"properties": {
"test_field": {
"type": "string",
"fielddata": {
"loading" : "eager"
}
}
}
}
~~~
query-time的fielddata生成和加载到内存,变为index-time,建立倒排索引的时候,会同步生成fielddata并且加载到内存中来,这样的话,对分词field的聚合性能当然会大幅度增强
2. 序号标记预加载
global ordinal原理解释
~~~
doc1: status1
doc2: status2
doc3: status2
doc4: status1
~~~
有很多重复值的情况,会进行global ordinal标记
~~~
status1 --> 0
status2 --> 1
doc1: 0
doc2: 1
doc3: 1
doc4: 0
~~~
建立的fielddata也会是这个样子的,这样的好处就是减少重复字符串的出现的次数,减少内存的消耗
~~~
POST /test_index/_mapping/test_type
{
"properties": {
"test_field": {
"type": "string",
"fielddata": {
"loading" : "eager_global_ordinals"
}
}
}
}
~~~
- springcloud
- springcloud的作用
- springboot服务提供者和消费者
- Eureka
- ribbon
- Feign
- feign在微服务中的使用
- feign充当http请求工具
- Hystrix 熔断器
- Zuul 路由网关
- Spring Cloud Config 分布式配置中心
- config介绍与配置
- Spring Cloud Config 配置实战
- Spring Cloud Bus
- gateway
- 概念讲解
- 实例
- GateWay
- 统一日志追踪
- 分布式锁
- 1.redis
- springcloud Alibaba
- 1. Nacos
- 1.1 安装
- 1.2 特性
- 1.3 实例
- 1. 整合nacos服务发现
- 2. 整合nacos配置功能
- 1.4 生产部署方案
- 环境隔离
- 原理讲解
- 1. 服务发现
- 2. sentinel
- 3. Seata事务
- CAP理论
- 3.1 安装
- 分布式协议
- 4.熔断和降级
- springcloud与alibba
- oauth
- 1. abstract
- 2. oauth2 in micro-service
- 微服务框架付费
- SkyWalking
- 介绍与相关资料
- APM系统简单对比(zipkin,pinpoint和skywalking)
- server安装部署
- agent安装
- 日志清理
- 统一日志中心
- docker安装部署
- 安装部署
- elasticsearch 7.x
- logstash 7.x
- kibana 7.x
- ES索引管理
- 定时清理数据
- index Lifecycle Management
- 没数据排查思路
- ELK自身组件监控
- 多租户方案
- 慢查询sql
- 日志审计
- 开发
- 登录认证
- 链路追踪
- elk
- Filebeat
- Filebeat基础
- Filebeat安装部署
- 多行消息Multiline
- how Filebeat works
- Logstash
- 安装
- rpm安装
- docker安装Logstash
- grok调试
- Grok语法调试
- Grok常用表达式
- 配置中常见判断
- filter提取器
- elasticsearch
- 安装
- rpm安装
- docker安装es
- 使用
- 概念
- 基础
- 中文分词
- 统计
- 排序
- 倒排与正排索引
- 自定义dynamic
- 练习
- nested object
- 父子关系模型
- 高亮
- 搜索提示
- kibana
- 安装
- docker安装
- rpm安装
- 整合
- 收集日志
- 慢sql
- 日志审计s
- 云
- 分布式架构
- 分布式锁
- Redis实现
- redisson
- 熔断和降级