
在日志分析、搜索系统、监控平台等场景中,Elasticsearch(ES)已成为实际上的标准。但许多团队在使用 ES 时,常常遇到:
- 磁盘空间暴涨,几天就吃掉上百 GB
- ⏳ 查询慢如蜗牛,聚合几秒变几分钟
- 字段类型混乱,text 和 keyword 混用导致功能异常
根本缘由?索引设计没做好!
今天,我们就来聊聊 Elasticsearch 7 的索引模板(Index Template)与 Mapping 设计最佳实践,帮你省下 50%+ 存储成本,提升 3 倍查询性能!
一、为什么必须用“索引模板”?
想象一下:你的 Nginx 日志每天生成一个新索引(nginx-access-2025.12.08),如果不预设规则,ES 会:
- 默认创建 1 主分片 + 1 副本
- 自动开启 动态映射(dynamic mapping)
- 所有字符串字段自动变成 text + keyword 双类型!
结果?
✅ 写入没问题
❌ 但:存储翻倍、无法控制分片、字段类型不可控!
✅ 正确做法:用可组合索引模板(Composable Templates)
ES 7.8+ 推荐使用 组件模板(Component Template) + 索引模板(Index Template) 的组合方式:
// 1. 先定义通用组件(复用!)
PUT _component_template/common_settings
{
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s"
}
}
}
// 2. 再定义业务模板
PUT _index_template/nginx_access
{
"index_patterns": ["nginx-access-*"],
"composed_of": ["common_settings"],
"priority": 200,
"template": {
"mappings": {
"properties": {
"client_ip": { "type": "ip" },
"url": { "type": "keyword", "ignore_above": 1024 },
"message": { "type": "text", "analyzer": "ik_max_word" }
}
}
}
}
✨ 优势:配置复用、优先级清晰、避免重复造轮子!
二、Mapping 字段设计 5 大黄金法则
✅ 1️⃣生产环境禁用dynamic: true!
默认 dynamic: true 会让任意新字段自动加入索引,极易导致:
- 字段爆炸(Field Explosion)
- 集群元数据膨胀
- 查询性能下降
正确姿势:
"mappings": {
"dynamic": "strict", // ← 拒绝未知字段
"properties": { ... }
}
或至少设为 “dynamic”: “false”(忽略但不报错)
✅ 2️⃣textvskeyword:别再混用了!
- 全文检索(如商品描述)→ 用 text
- 准确匹配/聚合/排序(如 user_id、status)→ 用 keyword
❌ 错误示例(动态映射默认行为):
"url": {
"type": "text",
"fields": {
"keyword": { "type": "keyword" } // ← 多余!
}
}
✅ 正确做法:
- 如果只用于聚合 → 直接 keyword
- 如果需要全文 + 准确 → 保留 .keyword 子字段,但限制长度:
- “url”: { “type”: “text”, “fields”: { “raw”: { “type”: “keyword”, “ignore_above”: 256 // 超长自动忽略,防内存溢出 } } }
✅ 3️⃣数值类型:能小则小!
|
场景 |
推荐类型 |
|
用户 ID(< 21 亿) |
integer ❌ 别用 long |
|
价格(保留 2 位小数) |
scaled_float(scaling_factor: 100) |
|
计数器(> 21 亿) |
long |
long 比 integer 多占 50% 存储空间!
✅ 4️⃣关闭无用功能,省空间又提速!
对不需要排序/聚合的字段,关闭 doc_values;不需要打分的,关 norms:
"log_message": {
"type": "text",
"index": true,
"doc_values": false, // ← 不用于聚合
"norms": false // ← 不参与相关性打分
}
实测:10 亿文档,关闭后 存储减少 18%,聚合快 2 倍!
✅ 5️⃣高基数字段慎用聚合!
像 user_id、session_id 这类高基数(High Cardinality)字段:
- 聚合会消耗大量内存
- 容易触发 circuit_breaking_exception
替代方案:
- 用 cardinality 近似去重
- 或改用 composite 聚合分页处理
三、额外加分项:ILM + 别名 = 运维无忧
- 用 ILM(生命周期管理)自动删除旧数据:
- “index.lifecycle.name”: “30days-delete”
- 用别名(Alias)无缝切换索引:
- “aliases”: { “nginx-access”: {} }
- 应用始终查 nginx-access,无需关心具体日期!
总结:一张表搞定最佳实践
|
模块 |
推荐配置 |
避坑指南 |
|
索引模板 |
可组合模板 + 高优先级 |
别用 legacy 模板 |
|
动态映射 |
dynamic: strict |
禁用 true |
|
字符串字段 |
按需选 text / keyword |
别默认双类型 |
|
数值类型 |
integer > long |
能小则小 |
|
存储优化 |
关 doc_values / norms |
对非聚合字段 |
|
运维 |
ILM + Alias |
自动化管理 |
结语
好的索引设计,是高性能 ES 集群的基石。
花 1 小时优化模板和 Mapping,能为你省下 数万元存储成本 和 无数个排查深夜!



