跳转至

ES 核心概念:与关系型数据库的对应关系


一、概念对应关系

flowchart LR
    subgraph Elasticsearch
        Index[Index\n索引]
        Document[Document\n文档]
        Field[Field\n字段]
        Mapping[Mapping\n映射]
        Shard[Shard\n分片]
        Replica[Replica\n副本]
    end

    subgraph 关系型数据库
        Table[Table\n表]
        Row[Row\n行]
        Column[Column\n列]
        Schema[Schema\n表结构]
        Partition[Partition\n分区]
        Slave[Slave\n从库]
    end

    Index <-->|对应| Table
    Document <-->|对应| Row
    Field <-->|对应| Column
    Mapping <-->|对应| Schema
    Shard <-->|类似| Partition
    Replica <-->|类似| Slave
ES 概念 数据库概念 说明
Index Table 存储同类文档的集合
Document Row 一条数据,JSON 格式
Field Field 文档中的一个字段
Mapping Schema 定义字段类型和索引方式
Shard Partition 数据分片,支持水平扩展
Replica 备库 副本分片,提供高可用

二、核心概念深度解析

2.1 Index(索引)

类比:相当于数据库中的一张表,但更像是一个"数据集合"。

  • 一个 Index 存储同类型的文档(如所有商品、所有订单)
  • Index 名称必须全小写
  • 创建时需要指定主分片数(创建后不可修改!)和副本分片数(可动态调整)
// 创建索引
PUT /products
{
  "settings": {
    "number_of_shards": 3,    // 主分片数,创建后不可改
    "number_of_replicas": 1   // 副本数,可动态调整
  },
  "mappings": {
    "properties": {
      "name": { "type": "text", "analyzer": "ik_max_word" },
      "price": { "type": "double" },
      "category": { "type": "keyword" }
    }
  }
}

⚠️ 面试陷阱:主分片数为什么创建后不可修改? 因为文档路由公式是 shard = hash(routing) % number_of_shards,修改分片数会导致已有文档找不到。


2.2 Document(文档)

类比:相当于数据库中的一行记录,但以 JSON 格式存储,天然支持嵌套结构。

// 一个商品文档
{
  "_index": "products",
  "_id": "1001",
  "_source": {
    "name": "iPhone 15 Pro",
    "price": 8999.0,
    "category": "手机",
    "tags": ["苹果", "5G", "旗舰"],
    "specs": {
      "color": "深空黑",
      "storage": "256GB"
    }
  }
}

文档元数据

字段 说明
_index 所属索引
_id 文档唯一 ID(不指定则自动生成)
_source 原始 JSON 数据
_score 相关性得分(查询时计算)
_version 版本号(乐观锁)

2.3 Mapping(映射)

类比:相当于数据库的 Schema(表结构),定义每个字段的类型索引方式

核心字段类型对比

类型 说明 典型场景
text 全文检索,会被分词 商品名称、文章内容
keyword 精确匹配,不分词 订单状态、用户 ID、标签
integer / long 整数 数量、年龄
double / float 浮点数 价格、评分
date 日期 创建时间、更新时间
boolean 布尔值 是否上架、是否删除
nested 嵌套对象(独立索引) 订单中的商品列表
geo_point 地理坐标 附近的人、门店定位

⚠️ 高频踩坑text vs keyword - text 字段会被分词,不能term 精确匹配,不能用于聚合排序 - keyword 字段不分词,只能精确匹配,可以用于聚合排序 - 同一字段需要既全文检索又精确匹配时,用 fields 多字段映射:

"title": {
  "type": "text",
  "analyzer": "ik_max_word",
  "fields": {
    "keyword": { "type": "keyword" }  // title.keyword 用于精确匹配
  }
}

动态 Mapping 的坑

flowchart LR
    A[写入新文档] --> B{字段是否存在 Mapping?}
    B -->|不存在| C[ES 自动推断类型]
    C --> D[字符串 → text + keyword]
    C --> E[整数 → long]
    C --> F[浮点 → float]
    D --> G[⚠️ 类型一旦确定无法修改\n只能 reindex 重建索引]

2.4 Shard(分片)

类比:相当于数据库的分区,将数据水平切分到多个节点。

flowchart TD
    subgraph ES 集群
        subgraph Node1[节点 1]
            P0[主分片 0]
            R1[副本分片 1]
        end
        subgraph Node2[节点 2]
            P1[主分片 1]
            R2[副本分片 2]
        end
        subgraph Node3[节点 3]
            P2[主分片 2]
            R0[副本分片 0]
        end
    end

    P0 -.->|复制| R0
    P1 -.->|复制| R1
    P2 -.->|复制| R2

分片核心规则

规则 说明
主分片数创建后不可修改 路由公式依赖分片数
副本分片不能与主分片在同一节点 保证高可用
副本分片可以承担读请求 提升读吞吐量
单个分片建议 10~50GB 过大影响恢复速度,过小增加管理开销

三、面试高频问题

Q1:ES 的 text 和 keyword 有什么区别?

text 会被分词器拆分,用于全文检索,不能精确匹配和聚合;keyword 不分词,用于精确匹配、过滤和聚合排序。同一字段需要两种能力时,用 fields 多字段映射。

Q2:为什么主分片数创建后不可修改?

文档路由公式 shard = hash(routing) % number_of_shards,修改分片数后,已有文档的路由结果改变,会找不到原来的数据。需要修改分片数只能通过 reindex 重建索引。

Q3:动态 Mapping 有什么风险?

ES 会自动推断字段类型,但推断可能不准确(如把数字字符串推断为 text),且字段类型一旦确定无法修改,只能删除索引重建或 reindex。生产环境建议关闭动态 Mapping,显式定义所有字段。

Q4:副本分片的作用是什么?

两个作用:① 高可用:主分片所在节点宕机时,副本分片自动提升为主分片;② 提升读性能:读请求可以路由到副本分片,分担主分片压力。


复习检验标准:能否解释 text 和 keyword 的区别?能否说出主分片数不可修改的原因?能否描述动态 Mapping 的风险?