Elasticsearch 完整教程

从零开始,深入掌握分布式搜索引擎的核心技术。涵盖基础CRUD操作、复杂查询DSL、聚合分析,到集群架构、性能优化与高级特性。

🚀 基础篇 ⚡ 中级篇 💎 高级篇
📚 目录导航

基础篇 - 核心概念

1 Elasticsearch 是什么?

Elasticsearch 是一个基于 Lucene 的分布式、RESTful 搜索和分析引擎。专为处理海量数据而设计,支持实时搜索、日志分析、安全分析等场景。

🔍 Elasticsearch 核心定位
Apache Lucene 全文检索库 Elasticsearch 分布式搜索引擎 RESTful API JSON over HTTP 全文搜索 日志分析 指标分析 水平扩展 高可用 实时性
💡 关键特性
  • 分布式架构:数据自动分片,支持 PB 级数据
  • 实时搜索:数据写入后 1 秒内可被搜索到
  • 全文检索:强大的 TF-IDF / BM25 相关性评分
  • 多租户:一个集群可承载多个索引
  • RESTful API:通过 HTTP 接口操作

2 核心概念:与 MySQL 对比理解

概念 ES 术语 MySQL 等价 说明
存储 Index(索引) Database(数据库) 逻辑命名空间,相当于表集合
存储 Document(文档) Row(行) JSON 格式的基本数据单元
字段 Field(字段) Column(列) 文档的属性
映射 Mapping(映射) Schema(表结构) 定义字段类型和分析方式
分片 Shard(分片) - 索引的水平拆分单元
副本 Replica(副本) - 分片的冗余拷贝,保证高可用
🏗️ ES 集群物理结构
Elasticsearch Cluster Node 1 (Master) Primary Shard P0 主分片 P1 主分片 R2 副本 Node 2 (Data) Replica + Primary R0 副本 P2 主分片 Node 3 (Data) Replica R1 副本 R2 副本 Primary (主分片) Replica (副本)
⚠️ 重要原则

主分片数在创建索引时就固定了,后续不能改变(除非 reindex)。
副本数可以随时调整。

索引与文档操作

1 创建索引

在 ES 中创建索引就像在 MySQL 中创建数据库和表。可以指定分片数、副本数、字段映射等。

PUT /products
# 创建索引 - 指定分片和副本设置
PUT /products
{
  "settings": {
    "number_of_shards": 3,        // 主分片数,创建后不可改
    "number_of_replicas": 1,      // 每个主分片的副本数
    "refresh_interval": "1s"    // 刷新间隔,默认1s
  },
  "mappings": {
    "properties": {
      "product_id":  { "type": "keyword" },
      "name":         { "type": "text", "analyzer": "standard" },
      "price":        { "type": "float" },
      "category":     { "type": "keyword" },
      "stock":        { "type": "integer" },
      "created_at":   { "type": "date" },
      "description":   { "type": "text" }
    }
  }
}

# 响应
{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "products"
}
✅ 字段类型选择建议
  • keyword - 用于精确匹配、过滤、排序、聚合(不分析)
  • text - 用于全文搜索,会被 analyzer 分词
  • integer/float/double - 数值类型,用于范围查询、排序
  • date - 日期类型,支持格式化
  • boolean - 布尔值
  • object / nested - 嵌套对象

2 文档 CRUD 操作

CRUD Operations
# ═══════════════════════════════════════════════════════════
#  CREATE - 创建文档(自动生成 ID)
# ═══════════════════════════════════════════════════════════
POST /products/_doc
{
  "product_id": "P001",
  "name": "iPhone 15 Pro",
  "price": 8999.00,
  "category": "手机",
  "stock": 100,
  "created_at": "2024-01-15T10:30:00Z",
  "description": "苹果最新款智能手机,搭载A17 Pro芯片"
}

# 响应
{
  "_index": "products",
  "_id": "abc123",        // 自动生成的 ID
  "_version": 1,          // 版本号,用于乐观锁
  "result": "created",
  "_seq_no": 0,
  "_primary_term": 1
}

# ═══════════════════════════════════════════════════════════
#  CREATE - 创建文档(指定 ID)
# ═══════════════════════════════════════════════════════════
PUT /products/_doc/P001
{
  "product_id": "P001",
  "name": "iPhone 15 Pro",
  "price": 8999.00,
  "category": "手机"
}

# ═══════════════════════════════════════════════════════════
#  READ - 读取文档
# ═══════════════════════════════════════════════════════════
GET /products/_doc/P001

# ═══════════════════════════════════════════════════════════
#  UPDATE - 更新文档(完整替换)
# ═══════════════════════════════════════════════════════════
PUT /products/_doc/P001
{
  "product_id": "P001",
  "name": "iPhone 15 Pro Max",   // 修改了 name
  "price": 9999.00,               // 修改了 price
  "category": "手机"
}

# ═══════════════════════════════════════════════════════════
#  PARTIAL UPDATE - 部分更新(只更新指定字段)
# ═══════════════════════════════════════════════════════════
POST /products/_update/P001
{
  "doc": {
    "price": 8799.00,     // 只更新价格
    "stock": 80        // 只更新库存
  }
}

# ═══════════════════════════════════════════════════════════
#  DELETE - 删除文档
# ═══════════════════════════════════════════════════════════
DELETE /products/_doc/P001

基础查询语法

1 Search API 基础

Search Query
# ═══════════════════════════════════════════════════════════
#  方式一:URI Search(简单参数查询)
# ═══════════════════════════════════════════════════════════
GET /products/_search?q=name:iPhone&size=10

# ═══════════════════════════════════════════════════════════
#  方式二:Request Body Search(推荐,功能更强大)
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": { /* 查询条件 */ },
  "from": 0,           // 起始位置(分页用)
  "size": 10,           // 返回数量
  "sort": [               // 排序
    { "price": "asc" },
    { "_score": "desc" }
  ],
  "_source": ["name", "price", "category"]  // 指定返回字段
}

# ═══════════════════════════════════════════════════════════
#  返回结构解读
# ═══════════════════════════════════════════════════════════
{
  "took": 15,              // 查询耗时(毫秒)
  "timed_out": false,       // 是否超时
  "hits": {
    "total": { "value": 42, "relation": "eq" },
    "max_score": 2.5,
    "hits": [           // 实际文档数组
      {
        "_index": "products",
        "_id": "P001",
        "_score": 2.5,    // 相关性评分
        "_source": { /* 文档内容 */ }
      }
    ]
  }
}

2 基础查询类型

Query Types
# ═══════════════════════════════════════════════════════════
#  1. match_all - 匹配所有文档
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "match_all": {}
  }
}

# ═══════════════════════════════════════════════════════════
#  2. match - 全文搜索(会被分析器分词)
#     搜索 "iPhone 手机",会分词为 ["iphone", "手机"] 分别匹配
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "match": {
      "name": "iPhone 手机"
    }
  }
}

#  match + operator(多词查询)
GET /products/_search
{
  "query": {
    "match": {
      "name": {
        "query": "iPhone Pro",
        "operator": "and"   // 必须包含所有词
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  3. term - 精确值查询(不分词,用于 keyword/numeric/date)
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "term": {
      "category": "手机"    // 精确匹配,不分词
    }
  }
}

#  terms - 多值精确匹配
GET /products/_search
{
  "query": {
    "terms": {
      "category": ["手机", "电脑"]
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  4. range - 范围查询
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 1000,    // >= 1000
        "lte": 5000     // <= 5000
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  5. bool - 布尔组合查询
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "bool": {
      "must": [         // 必须满足(AND,计分)
        { "match": { "name": "iPhone" } }
      ],
      "should": [        // 满足加分(OR)
        { "term": { "category": "手机" } }
      ],
      "filter": [        // 必须满足(AND,不计分)
        { "range": { "price": { "lte": 10000 } } }
      ],
      "must_not": [     // 必须不满足(NOT)
        { "term": { "stock": 0 } }
      ]
    }
  }
}
💡 must vs filter 的区别

must:计算相关性评分(_score),影响排序
filter:只做过滤,不计算评分,执行速度更快(利用缓存)

中级篇 - 复杂查询与 DSL

1 高级查询子句

Advanced Queries
# ═══════════════════════════════════════════════════════════
#  multi_match - 多字段匹配
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "iPhone 手机",
      "fields": ["name^2", "description", "category"],
      "type": "best_fields",    // 取最高分字段
      "tie_breaker": 0.3    // 其他字段的权重
    }
  }
}

# multi_match 类型说明:
# - best_fields: 取最高分(默认)
# - most_fields: 累加所有字段分数
# - cross_fields: 跨字段匹配(分词跨字段)
# - phrase: 短语匹配
# - phrase_prefix: 前缀短语匹配

# ═══════════════════════════════════════════════════════════
#  match_phrase - 短语匹配(保持顺序)
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "match_phrase": {
      "description": {
        "query": "A17 Pro 芯片",
        "slop": 2           // 允许词序移动的距离
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  prefix - 前缀查询
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "prefix": {
      "product_id": "P00"   // 匹配 P001, P002...
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  wildcard - 通配符查询
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "wildcard": {
      "product_id": "P*"    // 匹配任何以 P 开头的
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  exists - 存在性查询
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "exists": {
      "field": "description"   // 返回有 description 字段的文档
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  ids - ID 查询
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "ids": {
      "values": ["P001", "P002", "P003"]
    }
  }
}

2 嵌套查询与父子文档

📦 Object vs Nested 对比
Object 类型(不推荐关联查询) product_id: "P001" name: "iPhone 15" variants: [ {color: "黑", size: "128G"}, {color: "白", size: "256G"} ] ❌ 问题:color="黑" 和 size="256G" 可能被匹配到同一文档 Nested 类型(推荐关联查询) product_id: "P001" name: "iPhone 15" variants: [ {color: "黑", size: "128G"} {color: "白", size: "256G"} ] ✅ 优点:每个 variant 独立索引,精确匹配
Nested Query
# ═══════════════════════════════════════════════════════════
#  定义 nested 映射
# ═══════════════════════════════════════════════════════════
PUT /products
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "variants": {
        "type": "nested",        // 嵌套类型
        "properties": {
          "color": { "type": "keyword" },
          "size": { "type": "keyword" },
          "stock": { "type": "integer" }
        }
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  nested 查询 - 查询同一嵌套对象内的多个条件
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "nested": {
      "path": "variants",
      "query": {
        "bool": {
          "must": [
            { "term": { "variants.color": "黑色" } },
            { "term": { "variants.size": "256G" } }
          ]
        }
      }
    }
  }
}

聚合分析

1 聚合查询基础

📊 ES 聚合分类
Aggregations 聚合 Metrics 指标聚合 Bucket 桶聚合 Pipeline 管道聚合
Aggregations
# ═══════════════════════════════════════════════════════════
#  1. Metrics 聚合 - 单值指标
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "size": 0,              // 不返回文档,只返回聚合结果
  "aggs": {
    "avg_price": {          // 聚合名称
      "avg": { "field": "price" }
    },
    "max_price": {
      "max": { "field": "price" }
    },
    "min_price": {
      "min": { "field": "price" }
    },
    "sum_price": {
      "sum": { "field": "price" }
    },
    "total_docs": {
      "value_count": { "field": "product_id" }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  2. Bucket 聚合 - 分桶(类似 GROUP BY)
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "size": 0,
  "aggs": {
    "by_category": {
      "terms": {
        "field": "category",    // 按类别分桶
        "size": 10             // 返回前 10 个桶
      }
    },
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "key": "廉价", "from": 0, "to": 1000 },
          { "key": "中端", "from": 1000, "to": 5000 },
          { "key": "高端", "from": 5000 }
        ]
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  3. 多层嵌套聚合(桶 + 子聚合)
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "size": 0,
  "aggs": {
    "by_category": {
      "terms": { "field": "category" },
      "aggs": {                   // 子聚合
        "avg_price": {
          "avg": { "field": "price" }
        },
        "price_stats": {
          "stats": { "field": "price" }
        }
      }
    }
  }
}

2 常用聚合类型详解

聚合类型 说明 示例
avg / sum / min / max 基本数值统计 平均价格、总销量、最高分
stats 一次性返回所有统计 count, min, max, avg, sum
cardinality 去重计数(近似) UV 统计
percentiles 百分位数 P50, P90, P99 响应时间
percentile_ranks 百分位排名 有多少比例低于某值
histogram 直方图(数值间隔) 价格每 500 分组
date_histogram 日期直方图 按天/月/年分组
top_hits 返回桶内高分文档 每个类别销量前3
Advanced Aggregations
# ═══════════════════════════════════════════════════════════
#  cardinality - 去重计数(HyperLogLog 算法,近似值)
# ═══════════════════════════════════════════════════════════
GET /access_logs/_search
{
  "size": 0,
  "aggs": {
    "unique_users": {
      "cardinality": {
        "field": "user_id"
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  percentiles - 百分位数(TDigest 算法,近似值)
# ═══════════════════════════════════════════════════════════
GET /api_logs/_search
{
  "size": 0,
  "aggs": {
    "latency_percentiles": {
      "percentiles": {
        "field": "latency_ms",
        "percents": [50, 75, 90, 95, 99]
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  histogram - 价格分布直方图
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "size": 0,
  "aggs": {
    "price_distribution": {
      "histogram": {
        "field": "price",
        "interval": 500,       // 每 500 一个桶
        "min_doc_count": 1     // 最少文档数
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  date_histogram - 按月统计销售趋势
# ═══════════════════════════════════════════════════════════
GET /orders/_search
{
  "size": 0,
  "aggs": {
    "monthly_sales": {
      "date_histogram": {
        "field": "order_date",
        "calendar_interval": "month",
        "format": "yyyy-MM"
      },
      "aggs": {
        "revenue": {
          "sum": { "field": "amount" }
        }
      }
    }
  }
}

映射与分析器

1 分词器(Analyzer)原理

🔍 分词流程解析
输入文本 Character Filter 字符过滤器 html标签去除 符号替换 Tokenizer 分词器 按规则切分 记录位置/偏移 Token Filters 词过滤器 小写化/同义词 去停用词/词干 输出 tokens [iphone, 15, pro]
Analyzer Configuration
# ═══════════════════════════════════════════════════════════
#  内置分词器对比
# ═══════════════════════════════════════════════════════════

#  standard (默认) - 按空格/标点切分,小写化
#  "iPhone 15 Pro!" → ["iphone", "15", "pro"]

#  simple - 按字母切分,非字母字符分隔,小写化
#  "iPhone-15" → ["iphone", "15"]

#  whitespace - 按空格切分,不小写化
#  "iPhone 15 Pro" → ["iPhone", "15", "Pro"]

#  keyword - 不分词,整个字符串作为一个词
#  "iPhone 15 Pro" → ["iPhone 15 Pro"]

# ═══════════════════════════════════════════════════════════
#  自定义分词器
# ═══════════════════════════════════════════════════════════
PUT /my_index
{
  "settings": {
    "analysis": {
      "char_filter": {
        "my_char_filter": {
          "type": "mapping",
          "mappings": [
            "< => and",    // HTML 实体转换
            "> => or"
          ]
        }
      },
      "filter": {
        "my_synonym": {
          "type": "synonym",
          "synonyms": [
            "手机, phone, 移动电话",
            "电脑, computer, PC"
          ]
        },
        "my_stemmer": {
          "type": "stemmer",
          "language": "english"
        }
      },
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "char_filter": ["my_char_filter"],
          "tokenizer": "standard",
          "filter": ["lowercase", "my_synonym", "my_stemmer"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "analyzer": "my_analyzer"
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  IK 中文分词器示例(需要安装插件)
# ═══════════════════════════════════════════════════════════
#  安装:./bin/elasticsearch-plugin install analysis-ik

PUT /cn_index
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",   // 细粒度分词
        "search_analyzer": "ik_smart"    // 搜索时分词
      }
    }
  }
}

#  "中华人民共和国人民" →
#  ik_max_word: [中华, 中华人民共和国, 人民, 共和国, 国, 人, 民] 
#  ik_smart:   [中华人民共和国, 人民]

高级篇 - 集群与架构

1 集群原理与分片分配

🔄 分片分配流程
客户端请求 PUT /products/_doc/1 协调节点 Routing 路由计算 shard = hash(_id) % shards Primary Shard & Replica P0 Node1 R0 Node2 P1 Node2 R1 Node3 写入流程 1. 客户端发送请求到任意节点(协调节点) 2. 协调节点根据 _id hash 计算目标分片 3. 发送到对应 Primary Shard 并等待写入 4. Primary 同步到 Replica 后返回成功
Cluster Settings
# ═══════════════════════════════════════════════════════════
#  集群健康状态
# ═══════════════════════════════════════════════════════════
GET /_cluster/health

# 响应:
# {
#   "cluster_name": "my_cluster",
#   "status": "green",    // green/yellow/red
#   "number_of_nodes": 3,
#   "number_of_data_nodes": 3,
#   "active_shards": 45,
#   "relocating_shards": 0,
#   "active_primary_shards": 15
# }

# ═══════════════════════════════════════════════════════════
#  动态调整副本数
# ═══════════════════════════════════════════════════════════
#  提高可用性 - 增加副本
PUT /products/_settings
{
  "number_of_replicas": 2
}

# ═══════════════════════════════════════════════════════════
#  手动分片重新分配
# ═══════════════════════════════════════════════════════════
#  查看分片分配情况
GET /_cat/shards?v

#  手动移动分片(重新均衡)
POST /_cluster/reroute
{
  "commands": [
    {
      "move": {
        "index": "products",
        "shard": 0,
        "from_node": "node1",
        "to_node": "node2"
      }
    }
  ]
}

# ═══════════════════════════════════════════════════════════
#  集群级别设置
# ═══════════════════════════════════════════════════════════
PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.cluster_concurrent_rebalance": 2
  },
  "transient": {
    "indices.recovery.max_bytes_per_sec": "100mb"
  }
}

1 TF-IDF 与 BM25 算法

📐 相关性评分公式
TF-IDF 算法 Score = TF × IDF TF (词频) 词在文档中出现次数 × IDF (逆文档频率) log(N/df + 1) TF 公式:词出现次数 / 文档总词数 IDF 公式:log(总文档数 / 包含该词的文档数) 问题:词频无限累加,长文档得分偏高 BM25 算法 (ES 默认) Score = IDF × (tf × (k1+1)) / (tf + k1×(1-b+b×dl/avgdl)) tf: 词频 k1: 词频饱和度 (默认1.2) b: 文档长度归一化 (默认0.75) dl: 文档长度 avgdl: 平均文档长度 当 tf 增大时,增益递减 ✅ 解决了长文档得分过高的问题
Boost & Explain
# ═══════════════════════════════════════════════════════════
#  field_value_factor - 用字段值影响评分
#  评分 = 原始评分 × popularity^0.5
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { "name": "iPhone" }
      },
      "field_value_factor": {
        "field": "popularity",
        "factor": 1.2,
        "modifier": "sqrt",       // sqrt/half/log/square/none
        "missing": 1
      }
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  boost - 字段权重提升
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "iPhone 手机",
      "fields": [
        "name^3",           // name 权重 3
        "description^1",    // description 权重 1
        "category^2"       // category 权重 2
      ]
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  explain - 查看详细评分
# ═══════════════════════════════════════════════════════════
GET /products/_explain/P001
{
  "query": {
    "match": { "name": "iPhone" }
  }
}

性能优化

1 查询优化技巧

优化项 方法 效果
filter 缓存 用 filter 替代 must 避免重复计算评分
_source 过滤 只返回必要字段 减少网络传输
禁用 scoring constant_score + filter 跳过评分计算
分页深度 避免 deep pagination 防止内存爆炸
路由优化 使用 routing 参数 减少搜索分片
Performance Optimization
# ═══════════════════════════════════════════════════════════
#  1. 只返回需要的字段(_source filtering)
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "_source": {
    "includes": ["name", "price", "category"],  // 只返回这些字段
    "excludes": ["description"]                // 排除这些字段
  },
  "query": { "match_all": {} }
}

# ═══════════════════════════════════════════════════════════
#  2. constant_score - 不需要评分的查询
# ═══════════════════════════════════════════════════════════
GET /products/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": { "status": "active" }
      },
      "boost": 1.0
    }
  }
}

# ═══════════════════════════════════════════════════════════
#  3. 路由优化 - 直接定位分片
# ═══════════════════════════════════════════════════════════
#  写入时指定 routing(通常用 user_id)
POST /orders/_doc?routing=user_123
{
  "user_id": "user_123",
  "amount": 299,
  "product": "iPhone"
}

#  查询时使用相同 routing,只搜索一个分片
GET /orders/_search?routing=user_123
{
  "query": {
    "term": { "user_id": "user_123" }
  }
}

# ═══════════════════════════════════════════════════════════
#  4. 分页优化 - Search After(深度分页推荐)
# ═══════════════════════════════════════════════════════════
#  第一页
GET /products/_search
{
  "size": 10,
  "sort": [
    { "price": "asc" },
    { "_id": "asc" }
  ],
  "query": { "match_all": {} }
}

#  获取最后一页的 sort 值
#  第二页(使用 search_after)
GET /products/_search
{
  "size": 10,
  "sort": [
    { "price": "asc" },
    { "_id": "asc" }
  ],
  "search_after": [2999, "P005"],   // 上一页最后的 sort 值
  "query": { "match_all": {} }
}

# ═══════════════════════════════════════════════════════════
#  5. 预热查询 - 让热点数据进入 filesystem cache
# ═══════════════════════════════════════════════════════════
#  注册 searcher 预热
POST /products/_warmup
{
  "query": {
    "bool": {
      "should": [
        { "term": { "category": "手机" } },
        { "term": { "category": "电脑" } }
      ]
    }
  }
}

2 索引优化与别名

Index Optimization
# ═══════════════════════════════════════════════════════════
#  1. Index Alias - 索引别名(零停机切换)
# ═══════════════════════════════════════════════════════════
#  创建别名指向索引
POST /_aliases
{
  "actions": [
    { "add": { "index": "products_v1", "alias": "products" } }
  ]
}

#  创建新索引并切换别名(零停机 reindex)
POST /_aliases
{
  "actions": [
    { "remove": { "index": "products_v1", "alias": "products" } },
    { "add": { "index": "products_v2", "alias": "products" } }
  ]
}

# ═══════════════════════════════════════════════════════════
#  2. Reindex - 数据重建索引
# ═══════════════════════════════════════════════════════════
POST /_reindex
{
  "source": {
    "index": "products_v1",
    "size": 5000
  },
  "dest": {
    "index": "products_v2"
  }
}

# ═══════════════════════════════════════════════════════════
#  3. Force Merge - 段合并(减少 segments)
# ═══════════════════════════════════════════════════════════
#  合并后每个分片最多 1 个 segment,提升查询性能
POST /products/_forcemerge?max_num_segments=1

# ═══════════════════════════════════════════════════════════
#  4. Refresh vs Flush
# ═══════════════════════════════════════════════════════════
#  refresh - 使最近写入可被搜索(默认1s)
#  flush - 将 translog 刷盘,清空 translog,生成新 segment

#  批量写入后手动 refresh(需要立即可查)
POST /products/_bulk
{ "index": { "_id": "1" } }
{ "name": "iPhone" }
{ "index": { "_id": "2" } }
{ "name": "Samsung" }

POST /products/_refresh    // 使之立即可搜索

# ═══════════════════════════════════════════════════════════
#  5. 索引模板 - 自动应用配置
# ═══════════════════════════════════════════════════════════
PUT /_index_template/logs_template
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1
    },
    "mappings": {
      "properties": {
        "timestamp": { "type": "date" },
        "level": { "type": "keyword" },
        "message": { "type": "text" }
      }
    }
  }
}

3 集群调优参数

参数 默认值 优化建议
indices.memory.index_buffer_size 10% 写入量大时提高到 20-30%
indices.queries.cache.size 10% 查询命中率高时提高
thread_pool.write 核心数 写入瓶颈时可增大
thread_pool.search 核心数×3 查询瓶颈时可增大
indices.refresh_interval 1s 写入量大时改为 5s 或 -1(手动刷新)
Cluster Tuning
# ═══════════════════════════════════════════════════════════
#  集群级别优化配置
# ═══════════════════════════════════════════════════════════
PUT /_cluster/settings
{
  "persistent": {
    # 写入优化
    "indices.memory.index_buffer_size": "20%",
    "indices.refresh.interval": "5s",
    "indices.store.throttle.max_bytes_per_sec": "150mb",

    # 查询优化
    "indices.queries.cache.size": "15%",
    "thread_pool.write.queue_size": 1000,
    "thread_pool.search.queue_size": 1000
  }
}

# ═══════════════════════════════════════════════════════════
#  查看节点统计信息
# ═══════════════════════════════════════════════════════════
GET /_nodes/stats

#  查看索引统计
GET /products/_stats

#  查看 hot threads(排查慢查询)
GET /_nodes/hot_threads

恭喜你完成 ES 完整教程!

基础 ✓ 中级 ✓ 高级 ✓