Skip to content
ES
最佳实践与陷阱

最佳实践与陷阱

Elasticsearch 全手册的 🚨 陷阱、💡 最佳实践和 🔬 深层原理汇总,按主题索引。


安装与配置

# 类型 描述 参考
1 🚨 vm.max_map_count 过低 → ES 启动失败 00-安装与配置
2 🚨 宿主机数据目录权限不足(需要 chown 1000:1000 00-安装与配置
3 🚨 安装 IK / 拼音插件后未重启 → 不生效 00-安装与配置
4 🚨 插件版本与 ES 不匹配 → 节点启动失败 00-安装与配置
5 🚨 -Xms-Xmx 不相等 → JVM 动态 resizing 导致 GC 停顿 00-安装与配置
6 💡 JVM 堆内存不超过物理内存 50%,且不超过 32GB(指针压缩边界) 00-安装与配置
7 💡 剩余 50% 内存留给 OS 文件系统缓存(Lucene 严重依赖页缓存) 00-安装与配置
8 💡 生产环境启用 X-Pack 安全认证;永远不要用 elastic 超级用户跑应用 00-安装与配置
9 💡 使用 Docker Compose 统一管理 ES + Kibana,避免手动 docker run 00-安装与配置

核心概念与 Mapping

# 类型 描述 参考
1 🚨 Type 已废弃(ES 6.x deprecated,7.x 移除) 01-核心概念
2 🚨 Dynamic Mapping 猜错类型——第一个值决定字段类型,后续不一致报错 01-核心概念
3 🚨 index: false 字段不可搜索(但 _source 中仍可见) 01-核心概念
4 🚨 enabled: false 令整个 object 变成不索引的 blob,与 index 不同 01-核心概念
5 🚨 doc_values: false 则字段不可排序/聚合 01-核心概念
6 🚨 关闭 _source → 无法 Reindex / 无法 _update 01-核心概念
7 🚨 数组元素类型不一致([1, "two"])报错 01-核心概念
8 💡 几乎所有 text 字段都应配 .keyword 子字段(排序/聚合/精确过滤) 01-核心概念
9 💡 生产环境用显式 Mapping + Dynamic Template,避免动态推断 01-核心概念
10 🔬 倒排索引记录词条 → 文档映射 + 位置 + 偏移量(phrase match 和 highlight 的基础) 01-核心概念
11 🔬 Refresh(1s)= 可搜索;Flush(30min)= 持久化;Merge = 清理碎片 01-核心概念

索引与文档操作

# 类型 描述 参考
1 🚨 索引删除不可恢复(物理删除,无回收站机制) 02-索引与文档操作
2 🚨 Mapping 已有字段不可修改(类型/分词器锁定)→ 只能 Reindex 02-索引与文档操作
3 🚨 PUT 全量替换 → 未传字段被删除;用 POST /_update 做增量 02-索引与文档操作
4 🚨 _update 要求文档存在(不存在报 404)→ 用 upsert 02-索引与文档操作
5 🚨 Bulk API index vs createindex 覆盖旧文档,create 遇重复 ID 则报错 02-索引与文档操作
6 🚨 分片数创建后不可改 → 前期规划不足必须 Reindex 02-索引与文档操作
7 💡 让 ES 自动生成文档 ID(POST 不带 ID),避免 ID 查重开销 02-索引与文档操作
8 💡 大批量写入前关闭 refresh_interval-1),写完恢复 02-索引与文档操作
9 💡 零停机切换 = Alias 原子切换(remove old + add new) 02-索引与文档操作
10 💡 用 Index Template + Component Template 统一管理 Mappings 02-索引与文档操作
11 🔬 ES 文档不可变 → _update 底层仍是"标记删除 + 写入新文档" 02-索引与文档操作

查询

# 类型 描述 参考
1 🚨 termtext 字段查不到(text 写入时已分词,term 不分词) 03-查询详解
2 🚨 match 默认 OR 关系 → "mill lane" 匹配 mill lane 03-查询详解
3 🚨 filter 不参与评分 → 需要排序的场景必须用 must 03-查询详解
4 🚨 prefix / wildcard / regexp 是昂贵的前缀扫描,大索引上极慢 03-查询详解
5 🚨 object 嵌套查询可能误匹配(字段交叉匹配到不同子对象)→ 用 nested 03-查询详解
6 🚨 hits.total 超过 10000 不精确 → 设 track_total_hits: true 03-查询详解
7 🚨 function_score 不加 max_boost → 热门文档压制所有其他结果 03-查询详解
8 💡 精确值过滤用 filter(自动缓存 bitset),全文相关性排序用 must 03-查询详解
9 💡 minimum_should_match 控制精度-召回平衡 03-查询详解
10 🔬 BM25 引入词频饱和度——词频 1000 并非词频 100 的 10 倍权重 03-查询详解

排序、分页与高亮

# 类型 描述 参考
1 🚨 from + size > 10000 直接报错(max_result_window 限制) 04-排序分页与高亮
2 🚨 search_after 排序值不唯一 → 数据丢失;末尾加 _id 保底 04-排序分页与高亮
3 🚨 scroll 不清理 → 内存泄漏;用完务必 DELETE 04-排序分页与高亮
4 🚨 高亮字段与搜索字段不同名 → require_field_match: false 04-排序分页与高亮
5 💡 实时深度分页用 PIT + search_after(ES 7.10+),批量导出用 scroll 04-排序分页与高亮
6 💡 指定 sort 后 ES 自动停止打分(_score: null),能显著提升查询性能 04-排序分页与高亮
7 💡 对频繁高亮的字段启用 term_vector: with_positions_offsets,加速高亮 04-排序分页与高亮
8 🔬 深度分页性能差的根源:每个分片返回 from+size 条 → 协调节点对 分片数 × (from+size) 条排序 04-排序分页与高亮

数据聚合

# 类型 描述 参考
1 🚨 text 字段不可聚合 → 用 .keyword 子字段 05-数据聚合
2 🚨 Terms 聚合默认只返回 Top 10 → 设置 size 05-数据聚合
3 🚨 不设 size: 0 → 同时返回文档和聚合结果,浪费带宽 05-数据聚合
4 🚨 cardinality 是近似计数(HyperLogLog++,约 2% 误差) 05-数据聚合
5 🚨 date_histogram 用错间隔类型(DST 日不应用 fixed_interval 05-数据聚合
6 🚨 子聚合排序语法 "子聚合名.指标"(如 "stats_age.avg")易错 05-数据聚合
7 💡 先过滤再聚合(query 缩小范围),而非聚合后再过滤桶 05-数据聚合
8 🔬 Terms 聚合有分布式计数误差(各分片独立 Top N → 协调节点汇总) 05-数据聚合

搜索补全

# 类型 描述 参考
1 🚨 搜索时也使用拼音分词器 → 噪音结果 06-搜索补全
2 🚨 keep_original: false → 纯汉字搜索无法命中 06-搜索补全
3 💡 索引时拼音分词 + 搜索时 IK 分词(分析器分离策略) 06-搜索补全
4 💡 中文场景用拼音分词方案,英文/标签场景用 Completion Suggester(FST) 06-搜索补全

集群架构

# 类型 描述 参考
1 🚨 分片数创建后不可改(路由算法绑定 num_primary_shards 07-集群架构
2 🚨 默认节点角色混杂 → 生产应分离 master / data / coordinating 07-集群架构
3 🚨 master eligible 偶数 → 2 节点集群宕机一台即不可用 07-集群架构
4 🚨 单节点集群副本始终 unassigned → 集群状态 yellow 07-集群架构
5 🚨 集群 yellow 忽视 → 副本无冗余,再宕一台即数据丢失 07-集群架构
6 🚨 未配置 Rack Awareness → 所有副本可能在同一物理机架 07-集群架构
7 💡 每个索引至少 1 个副本(number_of_replicas: 1),确保宕机不丢 07-集群架构
8 💡 定时快照 + SLM 自动管理快照生命周期 07-集群架构
9 💡 时序数据用 Hot-Warm-Cold 分层 + ILM 自动迁移 07-集群架构
10 🔬 ES 7.0+ 内置 Raft-like 协调机制,脑裂问题一般不会发生 07-集群架构

性能调优 checklist

# 类别 建议 影响
1 写入 批量写入时 refresh_interval: -1,写完恢复 写入吞吐提升 2-5x
2 写入 使用 _bulk API,批次 5-15MB,注意 ES 的 HTTP 体大小限制 减少网络往返
3 写入 number_of_replicas: 0 先写再恢复副本(大批量导入) 写入吞吐翻倍
4 写入 让 ES 自动生成 _id(避免 ID 查重) 降低写入延迟
5 查询 filter 优先于 must(filter 自动缓存) 重复查询 10-100x 加速
6 查询 size: 0 用于纯聚合查询,不返回 hits 减少网络传输
7 查询 限制 from + size,用 search_after 做深度分页 避免 OOM
8 索引 _source 过滤只返回需要的字段 减少 IO 和网络
9 索引 doc_values: false 用于不需要排序/聚合的字段 节省磁盘
10 硬件 JVM 堆不超过 32GB(指针压缩边界),剩余内存留给 OS 页缓存 查询性能核心
11 硬件 使用 SSD,尤其是 Hot 节点 IOPS 决定写入和查询延迟
12 架构 Hot-Warm-Cold 分层 + ILM 自动管理 节省 50-70% 硬件成本

安全加固 checklist

# 建议
1 启用 X-Pack Security(ES 8.x+ 默认开启)
2 永远不要用 elastic 超级用户运行应用程序
3 为每个应用创建最小权限的 API Key 或角色
4 生产环境启用 HTTPS(xpack.security.http.ssl.enabled: true
5 节点间通信启用 TLS(xpack.security.transport.ssl.enabled: true
6 Kibana 不暴露公网 → 使用 SSH 隧道或 VPN
7 定期审计 GET /_security/_authenticate

常用监控命令

# 集群健康
GET /_cluster/health?level=indices

# 节点统计
GET /_nodes/stats/indices,jvm,os,fs

# 索引信息
GET /_cat/indices?v&s=store.size:desc

# 分片信息
GET /_cat/shards?v

# 慢查询
GET /_cluster/settings?include_defaults=true&filter_path=*.search.slowlog

# 待处理任务
GET /_cluster/pending_tasks

# Recovery 进度
GET /_cat/recovery?v

# 线程池统计
GET /_cat/thread_pool?v

# 段信息(检查 Merge 情况)
GET /_cat/segments?v

# Fielddata 使用情况
GET /_cat/fielddata?v

参考资料