Elasticsearch mapping 之 性能相关配置

ES 常见类型

通用类型:

二进制: binary

布尔型: boolean

字符串: keyword, constant_keyword, wildcard, text

别名: alias

对象: object, flattened, nested, join

结构化数据类型: Range, ip, version, murmur3

空间数据类型: geo_point, geo_shape, point, shape

性能相关参数

_all

_all 字段的索引方式是将所有其他字段的值作为一个大字符串索引的,通过include_in_all参数指定哪些字段的内容放入_all 字段,_all 字段在v6.0+已经废弃,v7.0正式移除,但是可以通过copy_to来实现_all相同功能.

python 复制代码
PUT /test_index
{
  "mappings": {
    "properties": {
      "field1": {
        "type": "text",
        "copy_to": "field_all"
      },
      "field2": {
        "type": "text",
        "copy_to": "field_all"
      },
      "field_all": {
        "type": "text"
      }
    }
  }
}

POST /test_index/_doc/1
{
  "field1": "smith",
  "field2": "John@example.com"
}

GET /test_index/_search
{
  "query": {
    "match": {
      "field_all": "smith"
    }
  }
}

现在field_all存的是["smith", "John@example.com"].

优点: 当我们想要查询field1或者field2中包含"smith"的时候,只要查询field_all字段就行. 不需要从两个字段的倒排索引中查询两遍.

**缺点:**我们不清楚"smith"是在field1还是field2, 需要按照字段或者"smith"在字段中的占比算score的时候就不支持了. 额外需要硬盘空间存储field_all字段内容.

_source

_source 字段用于存储 post 到 ES 的原始 json 文档。为什么要存储原始文档呢?因为 ES 采用倒排索引对文本进行搜索,而倒排索引无法存储原始输入文本。一段文本交给ES后,首先会被分析器(analyzer)打散成单词,为了保证搜索的准确性,在打散的过程中,会去除文本中的标点符号,统一文本的大小写,甚至对于英文等主流语言,会把发生形式变化的单词恢复成原型或词根,然后再根据统一规整之后的单词建立倒排索引,经过如此一番处理,原文已经面目全非。因此需要有一个地方来存储原始的信息,以便在搜到这个文档时能够把原文返回给查询者。和所有被存储的字段一样, _source 字段在被写入磁盘之前先会被压缩。

那么一定要存储原始文档吗?不一定!如果没有取出整个原始 json 结构体的需求,可以在 mapping 中关闭 source 字段或者只在 source 中存储部分字段(使用store)。但是这样做有些负面影响:

(1)不能获取到原文

(2)无法reindex:如果存储了 source,当 index 发生损坏,或需要改变 mapping 结构时,由于存在原始数据,ES可以通过原始数据自动重建index,如果不存 source 则无法实现

(3)无法在查询中使用script:因为 script 需要访问 source 中的字段

(4)如果没有 _source 字段,部分 update 请求不会生效。

如果不需要如上功能,可以禁用_source,减少空间或者指定字段储存到_source, 一般不建议禁用_source,可以通过设置best_compression高压缩比来代替禁用_source.

python 复制代码
PUT test_index
{
  "mappings": {
    "_source": {
      "enabled": false
    }
  }
}

PUT /test_index
{
  "mappings": {
    "_source": {
      "includes": [
        "field1"
      ],
      "excludes": [
        "field2"
      ]
    }
  }
}

store

store 决定一个字段是否要被单独存储。大家可能会有疑问,_source 里面不是已经存储了原始的文档嘛,为什么还需要一个额外的 store 属性呢?原因如下:

(1)如果禁用了 _source 保存,可以通过指定 store 属性来单独保存某个或某几个字段,而不是将整个输入文档保存到 _source 中。

(2)如果 _source 中有长度很长的文本(如一篇文章)和较短的文本(如文章标题),当只需要取出标题时,如果使用 _source 字段,ES需要读取整个 _source 字段,然后返回其中的 title,由此会引来额外的IO开销,降低效率。此时可以选择将 title 的 store 设置为true,在 _source 字段外单独存储一份。读取时不必在读取整 _source 字段了。但是需要注意,应该避免使用 store 查询多个字段,因为 store 的存储在磁盘上不连续,ES在读取不同的 store 字段时,每个字段的读取均需要在磁盘上进行查询操作,而使用 _source 字段可以一次性连续读取多个字段。

python 复制代码
PUT /test_index
{
  "mappings": {
    "properties": {
      "field1": {
        "type": "text",
        "copy_to": "field_all",
        "store": true
      },
      "field2": {
        "type": "text",
        "copy_to": "field_all"
      },
      "field_all": {
        "type": "text",
        "store": true
      }
    },
    "_source": {
      "enabled": false
    }
  }
}

GET /test_index/_search
{
  "stored_fields": ["field1", "field_all"]
}

doc_values

倒排索引可以提供全文检索能力,但是无法提供对排序和数据聚合的支持。如果没有doc_values, 聚合A字段流程如下:

  1. 通过倒排索引查询到匹配的docId列表
  2. 根据docId列表去各个分片获取到Doc的_source字段
  3. 解压缩_source字段获取json字符串里面的A字段
  4. 统一在内存中进行A字段的聚合

doc_values 本质上是一个序列化的列式存储结构,适用于聚合(aggregations)、排序(Sorting)、脚本(scripts access to field)等操作。当A字段开启doc_values时, 聚合A字段流程如下:

  1. 通过倒排索引查询到匹配的docId列表
  2. 根据docId列表去各个分片获取到Doc的doc_values里面的A字段, 由于doc_values是列存储,A字段在内存中是连续的,获取方便
  3. 统一在内存中进行A字段的聚合

默认情况下,ES几乎会为所有类型的字段存储doc_value,但是 text 或 text_annotated 等可分词字段不支持 doc values 。如果不需要对某个字段进行排序或者聚合,则可以关闭该字段的doc_value存储***(doc_values: false)**,关闭后不能进行聚合和排序操作*。

python 复制代码
PUT /test_index
{
  "mappings": {
    "properties": {
      "field1": {
        "type": "keyword",
        "copy_to": "field_all",
        "store": true
      },
      "field2": {
        "type": "keyword",
        "copy_to": "field_all",
        "doc_values": false
      },
      "field_all": {
        "type": "text",
        "store": true
      }
    },
    "_source": {
      "enabled": false
    }
  }
}

GET /test_index/_search
{
  "query": {
      "match_all": {}
  },
  "aggregations": {
    "terms_field2": {
      "terms": {
        "field": "field1"
      }
    }
  }
}

index

控制倒排索引,用于标识指定字段是否需要被索引。默认情况下是开启的,如果关闭了 index,则该字段的内容不会被 analyze 分词,也不会存入倒排索引,即意味着该字段无法被搜索。

python 复制代码
PUT /test_index
{
  "mappings": {
    "properties": {
      "field1": {
        "type": "keyword",
        "copy_to": "field_all",
        "store": true,
        "index": false
      },
      "field2": {
        "type": "keyword",
        "copy_to": "field_all",
        "doc_values": false
      },
      "field_all": {
        "type": "text",
        "store": true
      }
    },
    "_source": {
      "enabled": true
    }
  }
}

GET /test_index/_search
{
  "query": {
    "match": {
      "field1": "smith"
    }
  }
}

enabled

这是一个 index 和 doc_value 的总开关,如果 enabled 设置为false,则这个字段将会仅存在于 source 中,其对应的 index 和 doc_value 都不会被创建。这意味着,该字段将不可以被搜索、排序或者聚合,但可以通过 source 获取其原始值。

相关推荐
weixin_307779132 小时前
在AWS上使用KMS客户端密钥加密S3文件,同时支持PySpark读写和Snowflake导入
大数据·数据仓库·python·spark·云计算
weixin_307779139 小时前
Spark Streaming的背压机制的原理与实现代码及分析
大数据·python·spark
想做富婆13 小时前
hive:基本数据类型,关于表和列语法
大数据·hive·hadoop
梦醒沉醉14 小时前
单机伪分布Hadoop详细配置
大数据·hadoop·分布式
小Tomkk15 小时前
大数据相关职位介绍之一(数据分析,数据开发,数据产品经理,数据运营)
大数据·数据分析·数据开发·数据运营·数据产品经理
UI设计兰亭妙微15 小时前
大屏 UI 设计风格的未来趋势
大数据
乙卯年QAQ20 小时前
【Elasticsearch】Elasticsearch的查询
大数据·elasticsearch·搜索引擎
无敌小田田20 小时前
es数据同步
数据库·sql·elasticsearch
XianxinMao21 小时前
科技巨头AI投资引领未来增长
大数据·人工智能·科技
言之。21 小时前
【Spark速通】
大数据·分布式·spark