淺談ElasticSearch索引
概述
官方文檔:
索(suo)(suo)引是Elasticsearch中的(de)(de)基本存儲單元,類似于MySql數據庫中的(de)(de)表(biao),包(bao)含一堆有相似結構的(de)(de)文檔(dang)數據,在Elasticsearch可以創建多個索(suo)(suo)引。
tips:
每(mei)個(ge)(ge)索引默認有5個(ge)(ge)主(zhu)分片,1個(ge)(ge)副(fu)本分片,其中的(de)(de)主(zhu)分片和(he)副(fu)本分片的(de)(de)作用,我們(men)下面講(jiang)解。
添(tian)加至索(suo)引中的(de)數(shu)據(ju),會被(bei)近實時(shi)(1秒內)的(de)被(bei)搜索(suo)(這里不是(shi)立(li)即可以被(bei)檢索(suo))
近實(shi)時(shi)被搜索(suo)如何理解(jie)?下面我們會仔(zi)細講(jiang)解(jie),參考文檔:
索引的組成
邏輯層面
從邏(luo)輯(ji)層面(mian)來看(kan),索引是由下(xia)面(mian)幾個(ge)部分組成:
- 分片
- 索引的邏輯拆分單元,每個分片是一個獨立的 Lucene 索引
- 主分片(Primary Shards)負責數據寫入和讀取,副本分片(Replica Shards)用于容錯和負載均衡
- 分片數量在索引創建時指定,默認 5 個主分片,1個副本分片,可通過設置調整
設置分片示例
PUT /my_index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
- 映射(Mapping)
- 定義索引中字段,字段的類型、分詞器、存儲方式等元數據
- 支持動態映射(自動推斷字段類型)和手動映射(精確控制字段行為)
映射示例:
{
"mappings": {
"properties": {
"title": { "type": "text", "analyzer": "ik_max_word" },
"tags": { "type": "keyword" },
"create_time": { "type": "date" }
}
}
}
- 文檔(Document)
- 索引中真實的數據記錄,類似mysql表中的行數據
- 索引的最小數據單元,以 JSON 格式存儲,包含多個字段(Fields)
- 每個文檔有唯一標識符(ID),可自動生成或手動指定
示例文檔記錄
{
"_index": "my-first-elasticsearch-index",
"_id": "DyFpo5EBxE8fzbb95DOa",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": {
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [
"dolphins",
"whales"
]
},
"join_date": "2024/05/01"
}
}
物理層面
ES 索引的底層基(ji)于 Lucene,其物(wu)理存儲由以下部分(fen)構成(cheng):
- Lucene 分段(Segments)
- 索引的物理存儲單元,每個分段是一個獨立的倒排索引
- 分段由 Refresh 操作生成,包含文檔的索引數據和元數據
- 分段特性:
- 不可變(Immutable),生成后無法修改,保證搜索時的數據一致性
- 后臺自動合并(Merge),減少分段數量,優化搜索性能
- 倒排索引(Inverted Index)
- Lucene 的核心數據結構,是 ES 快速檢索的基礎
- 倒排索引將 “文檔 - 詞語” 的正向關系轉換為 “詞語 - 文檔列表” 的反向關系
結構示例:
詞語(Term) | 文檔ID列表(Postings List)
-----------|---------------------------
Elasticsearch | [1, 3, 5]
搜索引擎 | [1, 2, 4]
分布式 | [1, 3, 4]
-
索引文件(Index Files)
- 每個 Lucene 分段包含多個索引文件,常見類型:
- *.nvd:存儲文檔字段值
- *.nvm:字段值的元數據
- *.tim:記錄詞語(Term)的字典和頻率
- *.doc:文檔偏移量索引
- *.pos:詞語在文檔中的位置信息(用于短語搜索)
- *.dim:分段元數據(如創建時間、版本等)
- 每個 Lucene 分段包含多個索引文件,常見類型:
-
事務日志(Translog)
- 記錄所有未持久化的索引操作,確保數據不丟失
- 存儲路徑:
data/<cluster_name>/nodes/<node_id>/indices/<index_uuid>/translog - 作用:
- 保障 ES 重啟后數據恢復
- 支持增量恢復(Incremental Recovery)
索引分片的作用
主分片
主分片是 Elasticsearch(ES)索引數據存儲的基礎單元。也是實現ES分布式高可用的基石,主分片在創建索引時通過number_of_shards指定,默認是(shi)5個主(zhu)分(fen)片,主(zhu)分(fen)片的數量可以根據主(zhu)節點(dian)的數量來進(jin)行設置。
常規業務場景下(數據量中等,單分片≤50GB),每個節點的分片可以設置成1-2個,例如你的主節點有3個,在每個節點的資源規格都一樣的情況下,那么你的主分片可以設置為3個或者6個
大數據量場景下(單分片 50GB100GB,總數據量≤600GB),每個節點的分片可以設置成34個(ge),例如(ru)你的(de)(de)主節點(dian)有3個(ge),在每個(ge)節點(dian)的(de)(de)資源規格(ge)都一(yi)樣的(de)(de)情況下,那么你的(de)(de)主分片可以設置為9個(ge)或者12個(ge)
主分(fen)片經過設置(zhi)之后是(shi)不可更改的(de)(de),所以在設置(zhi)主分(fen)片時需要經過慎重(zhong)的(de)(de)考慮。
其主(zhu)要作用有以下(xia)幾點:
-
每(mei)個(ge)索(suo)(suo)引被拆分為(wei)多個(ge)主(zhu)分片(pian)(默(mo)認 5 個(ge)),每(mei)個(ge)主(zhu)分片(pian)是一(yi)個(ge)獨立(li)的 Lucene 索(suo)(suo)引,負責存儲索(suo)(suo)引的部分文檔數據,當執行搜索(suo)(suo)、更新、刪除(chu)等操(cao)作時,請求會被分發到相關(guan)主(zhu)分片(pian)上執行,確保數據操(cao)作的直接性(xing)和高(gao)效性(xing)。
-
主(zhu)分片是數據(ju)寫入的(de)(de)唯(wei)一入口(kou):所有文檔的(de)(de)創建(jian)、更新、刪(shan)除操(cao)作都(dou)首先(xian)在主(zhu)分片上完成(cheng),再同步到副本分片,主(zhu)分片維護著文檔的(de)(de)最新版本和元數據(ju)(如版本號、路由信息),確保集(ji)群內數據(ju)的(de)(de)一致性。
-
通過增加主(zhu)分(fen)(fen)(fen)片數量(創建索引(yin)時(shi)指(zhi)定(ding)),可以將(jiang)數據分(fen)(fen)(fen)散到更(geng)多節點(dian),提升(sheng)集(ji)群的存儲容量和并發(fa)處理能力。每(mei)個(ge)主(zhu)分(fen)(fen)(fen)片可獨立(li)分(fen)(fen)(fen)配(pei)(pei)到不同節點(dian),實現負(fu)載均(jun)衡(如通過 ES 的分(fen)(fen)(fen)片分(fen)(fen)(fen)配(pei)(pei)機制自動調(diao)整)。
副本分片
副本分片是主分片的鏡像拷貝,主要為集群提供可靠性、可用性和性能優化能力。副本分片占用與主分片相同的存儲空間,增加副本會提高內存和磁盤使用量,副本分片在創建索引時通過number_of_replicas指定,默認值是1。
副本分片設置之后是(shi)可以修(xiu)改的,如下:
PUT /your_index/_settings
{
"number_of_replicas": 2 // 設置副本數為2
}
副本分片的(de)作用(yong)如下:
-
當(dang)某個(ge)節點(dian)故障(zhang)或主分(fen)片所在節點(dian)不(bu)可(ke)用(yong)時(shi),副本(ben)分(fen)片會被提升為新的主分(fen)片(通過 ES 的自(zi)動故障(zhang)轉移機(ji)制),確保服務不(bu)中(zhong)斷,每個(ge)副本(ben)分(fen)片與(yu)主分(fen)片分(fen)布在不(bu)同節點(dian)(默認策略),避(bi)免單點(dian)故障(zhang)(如節點(dian)硬件故障(zhang)、網絡分(fen)區)導(dao)致數據丟失
-
副(fu)本(ben)分(fen)片(pian)可處理(li)讀(du)請(qing)求(如(ru)(ru)搜(sou)索(suo)、獲取文檔(dang)),分(fen)擔主分(fen)片(pian)的(de)查詢(xun)壓(ya)力(li),尤(you)其(qi)在(zai)高并(bing)發場景下顯著提升集群吞吐量,同一索(suo)引的(de)副(fu)本(ben)分(fen)片(pian)越多(duo),可并(bing)行處理(li)的(de)讀(du)請(qing)求越多(duo)(如(ru)(ru)每(mei)個(ge)副(fu)本(ben)分(fen)片(pian)可獨(du)立響應查詢(xun))。
-
副本分片是數據的冗余存儲,即使部分節點損壞,仍可通過其他節點的副本恢復完整數據(無需依賴外部備份),可通過調整副本數量(默認 1 個)平衡可用性和資源消耗(每個副本占用與主分片相同的存儲空間)。
修改副本分片的注意事項
- 注意資源消耗
- 每個副本分片占用與主分片相同的存儲空間,增加副本會提高內存和磁盤使用量。
- 例如5 主分片 ×2 副本 = 15 個分片,需預留相應存儲和 JVM 堆內存。
- 注意性能影響
- 增加副本可提升讀性能(更多分片可并行處理查詢),但修改期間會產生網絡流量(復制數據),可能短暫影響集群性能。
- 建議在低峰期執行大規模副本調整。
- 故障轉移能力
- 至少保留 1 個副本以保證高可用(允許 1 個節點故障)。
- 若需容忍 N 個節點故障,副本數應≥N。
- 集群狀態監控
- 修改過程中通過GET /_cluster/health監控集群狀態,確保status為green或yellow(red表示有未分配的主分片)
副本分片和主分片的數量對應關系
當主分片設置成3,副本分片設置成1時,那么一共會有6個分片存在集群中,副本分片的1是將對應的3個主分片分別copy一份在不同的節點中。

索引的近實時性
官方文檔:
近實時(shi)性是(shi)指當數據寫入至(zhi)ES的索(suo)引中,需要(yao)一定時(shi)間(官方描(miao)述的是(shi)1秒內)才能被檢索(suo)到,這個可以通(tong)過下面的參(can)數設置(zhi)
# 索引創建時設置refresh_interval為500ms
PUT /my_index
{
"settings": {
"refresh_interval": "500ms" # 默認1000ms,也就是1秒
}
}
refresh_interval參(can)數并(bing)不是設置的越(yue)小越(yue)好,當值(zhi)為0時,會(hui)禁用自(zi)動(dong) Refresh,仍需手動(dong)觸發 Refresh 才能讓文檔(dang)可搜索,這會(hui)引入人為延遲(chi)(人為操作(zuo),延遲(chi)可能更大)。
Refesh機制
Refresh 機制是控制近實(shi)時性的關鍵
- 默認 Refresh 間隔:ES 默認每 1 秒執行一次 Refresh 操作,這就是 “1 秒近實時” 的來源
- 手動觸發 Refresh:可通過 API 強制刷新,實現更低延遲(如POST /index/_refresh)
- 性能與實時性的權衡:縮短 Refresh 間隔會提高實時性,但會增加 IO 開銷;延長間隔則反之
為什么ES不是 “完全實時”的?
- Refresh 間隔的存在:即使將refresh_interval設為 0(禁用自動 Refresh),仍需手動觸發 Refresh 才能讓文檔可搜索,這會引入人為延遲。
- 寫入流程的固有延遲:文檔從寫入到生成分段需要經歷內存緩沖區處理,無法做到完全實時(如數據庫的實時查詢)。
- 設計權衡:ES 犧牲極小的實時性(1 秒)換取高性能和分布式架構的穩定性,這是分布式搜索系統的典型設計。
索引的管理
ES的(de)(de)(de)索(suo)引(yin)類似類似數(shu)據庫中(zhong)的(de)(de)(de)表,管(guan)理ES的(de)(de)(de)索(suo)引(yin)需要通(tong)過ES的(de)(de)(de)API來(lai)進行管(guan)理。索(suo)引(yin)的(de)(de)(de)API主要有以下
創建索引
API
PUT /{index}
{
"aliases": { ... }, # 指定索引別名
"settings": { ... }, # 指定索引的設置
"mappings": { ... } # 指定映射
}
參數說明:
index:索引的名稱,需要遵循以下規則:
- 僅限小寫字母
- 不能包含\、/、 *、?、"、<、>、|、#以及空格符等特殊符號
- 從7.0版本開始不再包含冒號
- 不能以-、_或+開頭
- 不能超過255個字節(注意它是字節,因此多字節字符將計入255個限制)
aliases:索(suo)(suo)(suo)引別名(Aliases) 是指(zhi)向一個或(huo)多個索(suo)(suo)(suo)引的邏輯名稱,可(ke)用于簡化查詢、實現讀(du)寫分離或(huo)索(suo)(suo)(suo)引滾動等場景
settings:索引(yin)的配置參(can)數,如分片數、副本數、刷(shua)新間隔等。常用的配置參(can)數為:
- number_of_shards:指定索引分片
- number_of_replicas:指定副本數
- refresh_interval:指定刷新時間,單位秒
- auto_expand_replicas:自動調整副本數(根據節點數)
- indices.memory.index_buffer_size:索引緩沖區占堆內存的比例(默認10%)
- index.translog.durability:異步刷新事務日志(默認sync)
- index.translog.flush_threshold_size:事務日志刷新閾值
- index.queries.cache.enabled:啟用查詢結果緩存(默認true)
- indices.queries.cache.size:緩存占堆內存比例
- indices.fielddata.cache.size:字段數據緩存大小
- index.priority:控制索引在恢復和分片分配時的優先級
- index.routing.allocation.include.tag:強制分片分配到特定節點,包含特定標簽的節點
- index.routing.allocation.exclude._name:強制分片分配到特定節點,排除特定節點
- index.blocks.write:true設置索引只讀
- index.hidden:true設置索引隱藏,不顯示在_cat/indices
- index.max_result_window:調整深度分頁限制,默認10000,慎用!推薦用scroll或search_after
mappings:定義索引字段(duan)的數據類型和(he)索引方式。后續會單獨講(jiang)解mappings
實戰:創建第一個索引
可以進入kibana進行創建:

示例:
# 創建請求
PUT index_test01
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "1s"
}
}
# 預期返回
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "index_test01"
}
查看索引
查看所有的索引
示例:
# 請求接口
GET /_cat/indices?v&s=index
# 預期返回
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .apm-agent-configuration KC2krPV1Q6On8zLG-2Ap6g 1 1 0 0 454b 227b
green open .apm-custom-link fW3LcrktTOGTDKvglhgODQ 1 1 0 0 454b 227b
green open .kibana_7.17.26_001 Bv6ZMZL6STaho_Phwbrv1w 1 1 691 16 5.3mb 2.8mb
green open .kibana_task_manager_7.17.26_001 0wrV35RzTWahe5vAUJKVow 1 1 17 25815 5.8mb 2.8mb
green open index_test01 TRTmGpiNRuC1wZY49Wt_aA 3 1 0 0 1.3kb 681b
返回字段說明:
- health:索引的健康程度,green表示所有主分片和副本分片都正常運行,red表示至少有一個主分片未分配(數據可能丟失),yellow表示主分片正常,但至少有一個副本分片未分配
- status:open表示索引可正常讀寫,close表示索引已關閉,不可訪問
- index:索引名稱,以 . 開頭的通常是系統索引,如 Kibana、APM 等組件創建的索引
- uuid:索引的唯一標識符(用于內部識別,不可修改)
- pri:主分片數量(創建索引時指定,不可動態修改)
- rep:主分片的副本數量(可動態調整)
- docs.count:索引中的文檔總數
- docs.deleted:已標記刪除但尚未物理刪除的文檔數(段合并后會清理)
- store.size:索引的總存儲大小(包括主分片和所有副本)
- pri.store.size:主分片的存儲大小(不包括副本)
查看指定的索引
api:GET /{index-name}
示例:
# 請求
GET /index_test01
# 預期返回
{
"index_test01" : {
"aliases" : { },
"mappings" : { },
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"refresh_interval" : "1s", # 刷新時間
"number_of_shards" : "3", # 主分片數量
"provided_name" : "index_test01", # 索引名稱
"creation_date" : "1750482108424", # 創建時間
"number_of_replicas" : "1", # 副本數量
"uuid" : "TRTmGpiNRuC1wZY49Wt_aA", # uuid,唯一標識符
"version" : {
"created" : "7172699"
}
}
}
}
}
其它查詢的api
| API 路徑 | 功能描述 | 示例 |
|---|---|---|
GET /{index}/_settings |
獲取索引設置 | GET /products/_settings |
GET /{index}/_mapping |
獲取索引映射 | GET /products/_mapping |
GET /{index}/_alias |
獲取索引別名 | GET /products/_alias |
GET /{index}/_stats |
獲取索引統計信息 | GET /products/_stats |
GET /{index}/_shards |
獲取分片狀態 | GET /products/_shards |
GET /_cluster/health |
集群健康狀態 | GET /_cluster/health |
GET /_cluster/health/{index} |
特定索引健康狀態 | GET /_cluster/health/products |
GET /{index}/_recovery |
恢復進度 | GET /products/_recovery |
GET /{index}/_segments |
段信息 | GET /products/_segments |
GET /{index}/_field_usage_stats |
字段使用統計 | GET /products/_field_usage_stats |
修改索引
在 Elasticsearch 中,修改索(suo)引(yin)設置的 API 允(yun)許(xu)動態(tai)調整索(suo)引(yin)的配置參數(如副本數、刷新間隔等)
動態修改索引設置(運行時生效)
修改單個或多個設置
示例:
PUT /{index}/_settings
{
"settings": {
"setting_name_1": "value_1",
"setting_name_2": "value_2",
...
}
}
修改副本數
# 請求
PUT /index_test01/_settings
{
"settings": {
"number_of_replicas": 2
}
}
# 預期返回
{
"acknowledged" : true
}
# 查看一下
GET /index_test01/_settings
{
"index_test01" : {
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"refresh_interval" : "1s",
"number_of_shards" : "3",
"provided_name" : "index_test01",
"creation_date" : "1750482108424",
"number_of_replicas" : "2",
"uuid" : "TRTmGpiNRuC1wZY49Wt_aA",
"version" : {
"created" : "7172699"
}
}
}
}
}
支持動態修改的參數
| 設置名稱 | 說明 | 示例值 |
|---|---|---|
| number_of_replicas | 副本數 | 2 |
| refresh_interval | 刷新間隔(控制新文檔可見性) | 30s, -1(禁用自動刷新) |
| index.search.slowlog.threshold.query.warn | 查詢慢日志閾值(警告級別) | 10s |
| index.max_result_window | 分頁最大結果數(深度分頁風險) | 100000 |
| index.blocks.write | 禁止寫入(只讀模式) | true |
| index.routing.allocation.exclude._name | 排除特定節點 | node1,node2 |
| index.priority | 恢復優先級 | 10 |
靜態設置參數(需關閉索引后修改)
某些設置(如主分片數(shu))必(bi)須在索引關閉(bi)后才能修(xiu)改:
# 關閉索引
POST /{index}/_close
# 修改靜態設置
PUT /{index}/_settings
{
"settings": {
"number_of_shards": 10 # 僅示例,生產環境謹慎修改
}
}
刪除索引(謹慎操作,可以使用關閉索引替代)
在 Elasticsearch 中,刪(shan)除(chu)索引(yin)是一個不(bu)可(ke)逆(ni)操作,會永久移除(chu)索引(yin)及其所(suo)有數(shu)據
刪除單個索引
api:DELETE /{index}
示例:
# 請求
DELETE /index_test01
# 預期返回
{
"acknowledged" : true
}
# 驗證索引是否存在
HEAD /index_test01
# 預期返回,404表示已經刪除
{"statusCode":404,"error":"Not Found","message":"404 - Not Found"}
刪除多個索引
使用逗(dou)號分隔(ge)多個索(suo)引名,或通配(pei)符匹配(pei):
示例:
DELETE /{index1},{index2},...
# 通配符,刪除所有以logs-開頭的索引
DELETE /logs-*
刪除所有索引(謹慎操作)
警告:此操作會刪除集群中所有索引,生產環境中禁用!
安全措施:部分集群配置了action.destructive_requires_name為true,禁止通過通配符(fu)刪除所有索引。
DELETE /_all
DELETE /*
索引的其它操作
- 關閉索引:
POST /{index}/_close,關閉索引,使其不能進行讀寫操作,以節省資源。 - 打開索引:
POST /{index}/_open,打開已關閉的索引,恢復其讀寫功能。 - 收縮索引:
POST /{index}/_shrink/{target_index},將索引收縮為指定的目標索引,可減少分片數量。 - 拆分索引:
POST /{index}/_split/{target_index},將索引拆分為多個新的索引。 - 克隆索引:
POST /{index}/_clone/{target_index},克隆一個現有的索引到新的索引。 - 索引滾動:
POST /{alias}/_rollover,用于將數據從一個索引滾動到另一個索引,常用于按時間滾動的索引場景。 - 凍結索引:
POST /{index}/_freeze,凍結索引,使其數據不可變,以節省內存和提高查詢性能。 - 解凍索引:
POST /{index}/_unfreeze,解凍已凍結的索引,恢復其可寫狀態。 - 解析索引:
GET /_resolve_index/{index},解析索引的名稱,返回其真實的索引名稱和相關信息。 - 檢查索引是否存在:
HEAD /{index},通過請求的響應狀態碼判斷索引是否存在,200 表示存在,404 表示不存在。
本文來自博客園,作者:huangSir-devops,轉載請注明原文鏈接://www.xtjzw.net/huangSir-devops/p/18933304,微信Vac666666,歡(huan)迎交流
