基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Elasticsearch中的静态 Mapping 和动态 Mapping 有什么区别?

知识点图片

在 Elasticsearch (ES) 中,Mapping (映射) 类似于关系型数据库(如 MySQL)中的 Schema(表结构定义)。它定义了索引中的文档包含哪些字段,以及这些字段的数据类型(如 text, keyword, integer, date 等)和索引方式。

Elasticsearch 支持两种 Mapping 方式:动态 Mapping (Dynamic Mapping)静态 Mapping (Explicit/Static Mapping)

以下是两者的详细区别和对比:


1. 动态 Mapping (Dynamic Mapping)

定义:
当你向一个不存在的索引写入文档,或者向已有索引写入包含新字段的文档时,Elasticsearch 会自动根据 JSON 数据的内容推断字段类型,并自动创建 Mapping。ES 号称 "Schemaless"(无模式)主要就是基于这个特性。

工作机制:
ES 依靠内置的规则来猜测数据类型:

  • JSON true/false \rightarrow boolean
  • JSON 整数 \rightarrow long
  • JSON 浮点数 \rightarrow float
  • JSON 字符串 \rightarrow text (带 keyword 子字段) 或 date (如果符合日期格式)

优点:

  • 上手快: 不需要预先定义结构,直接写入数据即可,非常适合开发初期或原型验证。
  • 灵活性高: 能够自动适应字段的变化(新增字段)。

缺点:

  • 类型推断可能不准确: 例如,你希望存储为 integer 的 ID 字段(如 "123")可能被推断为 text,或者日期格式推断错误。
  • 资源浪费: 默认字符串会被映射为 textkeyword 双重字段,这会占用更多磁盘空间和内存。
  • Mapping Explosion (映射爆炸): 如果数据中有大量不确定的动态字段,会导致 Mapping 过大,影响集群性能。

2. 静态 Mapping (Explicit Mapping / 显式映射)

定义:
开发者在创建索引时,手动定义好字段的名称、数据类型、分词器(Analyzer)等属性。这相当于在 SQL 中执行 CREATE TABLE 语句。

工作机制:
你需要通过 API 显式地告诉 ES:“title 字段是 text 类型,使用 ik_max_word 分词器;age 字段是 integer 类型”。

优点:

  • 精准控制: 可以精确指定字段类型(如使用 byte 代替 long 节省空间),指定分词器,配置 null_value 等。
  • 性能优化: 避免了不必要的字段索引(例如只存不搜的字段设为 index: false),节省存储和 CPU。
  • 数据质量保障: 防止脏数据污染。如果定义了 age 是数字,写入 "abc" 会报错(取决于配置),从而保证数据类型一致性。

缺点:

  • 前期工作量大: 需要预先了解数据结构并编写 Mapping JSON。
  • 灵活性较差: 字段定义后,通常不能修改已有字段的类型(因为这会使已索引的数据失效),只能通过 Reindex(重建索引)来解决。

3. 核心区别对比表

特性 动态 Mapping (Dynamic) 静态 Mapping (Explicit)
创建方式 自动推断,随数据写入自动创建 手动通过 API 预先定义
灵活性 高,自动处理新字段 低,需严格遵守预定义结构
准确性 基于猜测,可能出错 100% 准确,由开发者掌控
存储空间 通常较大(默认冗余索引) 较小(可优化)
适用场景 开发测试、日志类数据、字段不确定的场景 生产环境、核心业务数据、搜索调优场景
维护成本 低(前期),高(后期可能需清理) 高(前期),低(后期稳定)

4. 进阶:如何结合使用?(最佳实践)

在生产环境中,通常不会非黑即白地只选一种,而是结合使用。

A. 控制动态行为 (dynamic 参数)

你可以在静态 Mapping 中设置 dynamic 参数来控制如何处理未定义的新字段

  1. dynamic: true (默认):允许自动新增字段(动态 Mapping 行为)。
  2. dynamic: false:新字段会被忽略(不被索引,无法搜索,但会出现在 _source 中)。
  3. dynamic: 'strict':遇到新字段直接报错,拒绝写入。这是最严格的模式,适合核心业务表。

B. 动态模板 (Dynamic Templates)

这是一种“半自动”的方式。你可以定义规则,告诉 ES:“如果遇到以 is_ 开头的字段,就自动映射为 boolean” 或者 “如果遇到字符串类型,统一映射为 keyword”。

示例:

json
PUT my_index
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ],
    "properties": {
      "title": { "type": "text" },  // 静态定义
      "age":   { "type": "integer" } // 静态定义
    }
  }
}

总结

  • 想省事、不确定数据结构 \rightarrow动态 Mapping
  • 要性能、要精准搜索、生产环境 \rightarrow 必须用 静态 Mapping
  • 高手做法 \rightarrow 静态 Mapping 定义核心字段 + dynamic: strict 防止脏数据 + Dynamic Templates 处理特定规则的动态字段。
00:00
00:00