Elasticsearch 索引(Index) 是数据组织与管理的核心单元,类似于关系型数据库中的“数据库”或“表”。理解索引的结构、配置、生命周期和最佳实践,是掌握 Elasticsearch 的关键。
本文将全面详解 Elasticsearch 索引的概念、组成、配置项、操作方式及高级用法。
一、什么是索引(Index)?
在 Elasticsearch 中,索引(Index) 是一个逻辑命名空间,用于存储具有相似特征的文档集合。它是数据写入、搜索、聚合和管理的基本单位。
类比关系型数据库:
| Elasticsearch | 关系型数据库(如 MySQL) |
|---|---|
| Index | Table / Database |
| Document | Row |
| Field | Column |
| Mapping | Schema |
📌 注意:Elasticsearch 的“索引”更接近于“表”的概念,但功能更强大。
二、索引的核心组成
一个完整的索引由以下几个部分构成:
| 组成部分 | 说明 |
|---|---|
| Settings | 配置分片数、副本数、分析器等 |
| Mappings | 定义字段类型、是否分词、是否索引等 |
| Documents | 实际存储的数据(JSON 文档) |
| Shards & Replicas | 物理存储结构,支持水平扩展和高可用 |
三、索引的基本操作(CRUD)
1. 创建索引(Create)
最简创建:
PUT /my-index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"title": { "type": "text" },
"status": { "type": "keyword" },
"created_at": { "type": "date" }
}
}
}
⚠️ 索引名必须小写,不能包含特殊字符(
_、-可用)。
2. 查看索引信息
GET /my-index
返回:
{
"my-index": {
"aliases": {},
"mappings": { ... },
"settings": { ... }
}
}
查看所有索引:
GET /_cat/indices?v
3. 删除索引
DELETE /my-index
⚠️ 删除不可恢复,请谨慎操作。
4. 打开/关闭索引
关闭索引可节省资源(内存),但仍保留数据:
POST /my-index/_close
POST /my-index/_open
四、索引 Settings 详解
settings 控制索引的物理行为和性能。
常见配置项:
| 参数 | 说明 | 默认值 |
|---|---|---|
number_of_shards | 主分片数量(创建后不可改) | 1 |
number_of_replicas | 每个主分片的副本数 | 1 |
refresh_interval | 刷新频率(控制近实时搜索) | 1s |
index.codec | 存储压缩方式 | default(可设为 best_compression) |
analysis.analyzer | 自定义分析器 | 见下文 |
示例:高写入场景优化
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1,
"refresh_interval": "30s",
"translog.durability": "async",
"translog.sync_interval": "30s"
}
提示:写入密集型应用可降低刷新频率以提升吞吐。
五、索引 Mappings 详解
mappings 定义字段的结构和行为,决定如何索引和搜索。
1. 核心字段类型
| 类型 | 用途 | 是否分词 |
|---|---|---|
text | 全文搜索(会分词) | ✅ |
keyword | 精确匹配、聚合、排序 | ❌ |
date | 日期类型 | - |
long, integer, short, byte | 整数 | |
double, float | 浮点数 | |
boolean | 布尔值 | |
object | 嵌套 JSON 对象 | |
nested | 独立索引的嵌套对象 | |
ip | IP 地址 | |
geo_point | 地理位置坐标 |
2. 动态映射 vs 静态映射
-
动态映射(Dynamic Mapping)
自动推断字段类型(如字符串 →text+keyword)。 -
静态映射(Explicit Mapping)
手动定义字段类型,避免类型冲突。
"mappings": {
"dynamic": false, // 禁用动态映射
"properties": {
"email": { "type": "keyword" },
"content": { "type": "text", "analyzer": "ik_smart" }
}
}
建议生产环境关闭
dynamic或设为strict(拒绝未知字段)。
3. 自定义分析器(Analyzer)
用于控制 text 字段的分词方式。
示例:使用 IK 中文分词
PUT /news
{
"settings": {
"analysis": {
"analyzer": {
"my_ik_analyzer": {
"type": "custom",
"tokenizer": "ik_max_word"
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "my_ik_analyzer"
}
}
}
}
常用中文分词插件:ik、jieba、analysis-smartcn。
六、分片(Shards)与副本(Replicas)
1. 主分片(Primary Shard)
- 数据被分割成多个主分片,分布在不同节点上。
number_of_shards在创建时设定,不可更改。- 建议:根据数据量预估(如每 shard 30GB 左右)。
2. 副本分片(Replica Shard)
- 每个主分片可有多个副本,用于:
- 高可用(主分片故障时切换)
- 提升查询吞吐(负载均衡)
"settings": {
"number_of_shards": 3,
"number_of_replicas": 2 // 每个主分片有 2 个副本
}
总分片数 = 主分片 × (1 + 副本数) = 3 × 3 = 9
3. 分片设计建议
- 单个分片建议 10GB ~ 50GB。
- 集群节点数 ≥ 主分片数,以便均匀分布。
- 避免“过小分片”(影响性能)或“过大分片”(恢复慢)。
七、索引别名(Aliases)
别名 是指向一个或多个索引的逻辑名称,用于:
- 无缝切换索引(如滚动更新)
- 实现读写分离
- 联合多个索引查询
示例:读写别名
# 创建索引
PUT /logs-2024-04-01
# 添加别名
POST /_aliases
{
"actions": [
{ "add": { "index": "logs-2024-04-01", "alias": "logs-write" } },
{ "add": { "index": "logs-2024-04-01", "alias": "logs-read" } }
]
}
# 写入
POST /logs-write/_doc { ... }
# 查询
GET /logs-read/_search { ... }
滚动更新(Rollover)场景
PUT /logs-000001
{
"aliases": {
"logs-write": {
"is_write_index": true
},
"logs-read": {}
}
}
# 当满足条件时滚动到新索引
POST /logs-write/_rollover
{
"conditions": {
"max_age": "1d",
"max_docs": 1000000
}
}
八、索引模板(Index Templates)
用于自动应用 settings 和 mappings 到匹配名称的索引。
1. Legacy Template(旧版)
PUT /_template/template_logs
{
"index_patterns": ["logs-*"],
"settings": {
"number_of_shards": 3
},
"mappings": {
"properties": {
"host": { "type": "keyword" }
}
}
}
2. Composable Template(7.8+ 推荐)
支持多模板组合:
# 组件模板:定义 mappings
PUT /_component_template/logs-mapping
{
"template": {
"mappings": {
"properties": {
"message": { "type": "text" }
}
}
}
}
# 组合模板
PUT /_index_template/logs-template
{
"index_patterns": ["logs-*"],
"template": {
"settings": {
"number_of_shards": 3
},
"composed_of": ["logs-mapping"]
}
}
九、索引生命周期管理(ILM)
ILM(Index Lifecycle Management) 自动管理索引从创建到删除的全过程。
四个阶段:
- Hot:活跃写入,高资源。
- Warm:不再写入,只读,降低副本、禁用刷新。
- Cold:极少访问,迁移到低性能节点。
- Delete:过期删除。
示例策略:
PUT /_ilm/policy/logs-policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": { "max_size": "50gb", "max_age": "30d" }
}
},
"warm": {
"min_age": "30d",
"actions": {
"forcemerge": { "max_num_segments": 1 },
"shrink": { "number_of_shards": 1 }
}
},
"delete": {
"min_age": "365d",
"actions": { "delete": {} }
}
}
}
}
应用到模板:
"template": {
"settings": {
"index.lifecycle.name": "logs-policy"
}
}
十、高级特性与最佳实践
1. 数据分区策略
- 时间序列索引:
logs-2024-04-01,便于按时间管理。 - 按业务分索引:
users、orders、products。 - 避免单一超大索引。
2. 性能优化建议
- 合理设置
refresh_interval。 - 使用
keyword替代text做聚合。 - 控制字段数量(避免“宽表”)。
- 启用
doc_values(默认开启,用于排序聚合)。
3. 安全与权限
- 使用 Index Patterns + Roles 控制用户访问。
- 敏感字段加密(需应用层或使用 Field Masking)。
十一、常见问题
Q1:如何修改已创建索引的分片数?
❌ 不能直接修改。
✅ 解决方案:使用 reindex 创建新索引并迁移数据。
POST /_reindex
{
"source": { "index": "old-index" },
"dest": { "index": "new-index" }
}
Q2:索引可以跨集群吗?
不能直接跨集群,但可通过 Cross-Cluster Search 查询远程集群的索引。
Q3:如何监控索引状态?
GET /my-index/_stats # 统计信息
GET /my-index/_recovery # 恢复状态
GET /_cat/shards/my-index?v # 分片分布
十二、总结
| 特性 | 说明 |
|---|---|
| Index | 数据逻辑容器 |
| Settings | 控制分片、副本、刷新等 |
| Mappings | 定义字段结构与行为 |
| Shards | 水平扩展的基础 |
| Aliases | 实现灵活路由 |
| Templates | 自动化索引配置 |
| ILM | 自动化生命周期管理 |
十三、最佳实践清单 ✅
- 使用时间序列命名(如
logs-%Y-%m-%d) - 配置 ILM 实现自动 rollover 和删除
- 使用别名实现读写分离
- 关闭
dynamic或设为strict - 合理设置分片数(每分片 10~50GB)
- 中文字段使用
ik分词器 - 高频聚合字段使用
keyword
📌 扩展学习建议:
- 索引模板 + ILM + Rollover 联合使用(日志系统标准架构)
- Hot-Warm-Cold 架构设计
- 使用 Kibana Stack Management 管理索引
- 监控索引的 segment 数量、merge 压力
893

被折叠的 条评论
为什么被折叠?



