Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

ElasticSearch 最佳实践

目录

  • 索引设计
  • Mapping 设计
  • 写入优化
  • 搜索优化
  • 分片与节点规划
  • 运维与监控
  • 常见反模式
  • 安全与稳定性
  • 日志/搜索/电商三类场景最佳实践

🌟 1. 索引(Index)最佳实践

1.1 一个索引数据量控制在 30–50GB / shard

理由:

  • 分片太大:迁移困难,恢复慢
  • 分片太小:shard 过多(浪费内存)

推荐:

总数据量 / 40GB = 推荐 shard 数量

1.2 按日期滚动(日志类)

不要把日志全部写入 logs 索引。

正确:

logs-2025.01.01
logs-2025.01.02

配合 ILM 自动 rollover。

1.3 禁止自动建索引(必做)

action.auto_create_index: false

避免野生索引,避免 mapping 爆炸。

1.4 避免一个索引有上千个字段(field explosion)

ES 的 field 越多,内存越高、查询越慢。

限制:

"index.mapping.total_fields.limit": 1000

🌟 2. Mapping 最佳实践

2.1 text + keyword 双字段模式(最经典)

"title": {
  "type": "text",
  "fields": {
    "raw": { "type": "keyword" }
  }
}

用途:

  • title 做全文搜索
  • title.raw 做排序、聚合

2.2 状态字段绝不使用 text

错误(非常损性能):

"status": "text"

正确:

"status": "keyword"

所有枚举类字段都用 keyword。

2.3 避免 nested 过多(nested 查询非常慢)

如果可以:

  • 用对象数组替代
  • 或者扁平化结构(denormalization)

2.4 禁止 dynamic mapping(生产必须关闭)

"dynamic": "strict"

减少字段爆炸 + 防止垃圾数据污染索引。

🌟 3. 写入(Indexing)最佳实践

3.1 使用 bulk 批量写入

每批 1k–5k 文档最佳。

3.2 刷新间隔调整(写入量大时)

默认 1s 刷新太频繁,写入吞吐下跌。

日志类场景:

"refresh_interval": "30s"

普通业务:

"refresh_interval": "5s"

3.3 写入高峰时减少副本数

高写入场景(如导入大量数据):

number_of_replicas: 0

导入完成后再改回:

number_of_replicas: 1

3.4 translog 配置

写密集型应用:

index.translog.durability: async
index.translog.sync_interval: 30s

吞吐量极大提升。

🌟 4. 搜索(Query)最佳实践

4.1 查询优先使用 filter(缓存 + 不评分)

"bool": {
  "filter": [
    {"term": {"status": "active"}}
  ]
}

filter 查询性能极高,搜索缓存命中多。

4.2 避免 wildcard、regexp、prefix 过度使用

有以下情况请选择:

场景 替代方式
前缀匹配 prefix edge_ngram
模糊查询 fuzzy(有限度)
模糊匹配 ngram

4.3 避免深度分页

不要:

from: 200000

改用:

  • search_after
  • 或者 scroll(导出大量数据)

4.4 聚合字段必须是 keyword

text 字段不能聚合。

4.5 打分高质量搜索统一用 bool + boost

提高主字段评分:

"match": {
  "title": {
    "query": "python",
    "boost": 3
  }
}

🌟 5. 分片(Shard)最佳实践

5.1 分片过多是 ES 性能杀手

症状:

  • JVM heap 爆高
  • 集群变慢
  • 集群恢复时间过长

原则:

  • 只分够接下来 1 年的量,不要多
  • 每节点 shard 数 ≤ 20 × CPU 核数(经验值)

5.2 副本数根据场景动态调整

场景 副本数
日志写入高峰 0
正常业务 1
高读取量 2–3

🌟 6. 运维最佳实践

6.1 禁用 swap(必须)

bootstrap.memory_lock: true

6.2 JVM heap = 物理内存 50%

不要超过 32GB(否则关闭压缩指针,性能直线下降)。

6.3 SSD,禁用机械硬盘(HDD)

ES 对磁盘 IO 非常敏感。

6.4 使用 ILM 管理索引生命周期

自动:

  • rollover
  • warm / cold / frozen
  • delete

6.5 snapshot 数据备份必须有

快照恢复是分布式集群核心能力。

6.6 使用专用 master(3 节点)

生产必须分离:

  • master
  • data

🌟 7. 常见反模式(千万别这么做)

❌ 反模式 原因
一个索引几百 GB 分片迁移慢,恢复慢
全字段 dynamic mapping 字段爆炸
搜索用 wildcard “*” 前缀 全表扫描
from=100000 深分页 慢死
所有字段都 text 聚合、排序无效
keyword 做全文搜索 匹配不到
JVM heap > 32GB 禁用压缩指针
一个节点 1000 shard OOM 风险

🌟 8. 安全最佳实践

  • 启用 xpack.security
  • HTTPS 传输
  • API key 管理服务之间权限
  • 索引级别权限
  • Kibana + Spaces + RBAC

🌟 9. 三大常见场景最佳实践

9.1 日志系统(ELK)

  • index 按天滚动
  • refresh_interval = 30s
  • replicas = 0(高峰)
  • keyword 用于聚合
  • 禁止 wildcard 全模糊
  • 使用 ILM

9.2 电商搜索(结构化 + 文本)

  • 标题 text + keyword.raw
  • 分类 keyword
  • 价格 range + 数字类型
  • 日期 date
  • 使用 search_after 分页

9.3 文本向量检索(dense_vector)

  • 使用 HNSW(ES8 默认)
  • 维度 ≤ 2048
  • 使用 knn 查询