当前位置: 首页 > article >正文

Elasticsearch 优化方案

一、概要

Elasticsearch 优化是一个系统工程,需要根据实际业务场景、数据特点和查询模式进行针对性调整。关键优化方向包括:

  1. 精心设计索引结构:字段类型选择,生命周期管理。
  2. 优化查询DSL:避免高开销操作,合理使用缓存。
  3. 提升写入效率:批量操作,调整刷新策略。
  4. 保障硬件资源:足够的内存、高性能存储和网络。
  5. 合理规划集群架构:节点角色分离,分片策略优化。
  6. 持续监控维护:定期健康检查,性能调优。

二、索引设计优化

  1. 索引结构优化

    1. 数据类型选择优化:

      • 避免过度使用 text 类型:对于不需要全文搜索的字段,使用 keyword 类型更高效。
      • 数值类型选择:根据实际范围选择最小够用的类型(byte, short, integer, long, float, double)。
      • 地理数据:使用 geo_point 或 geo_shape 而非字符串存储。
      • 日期类型:始终使用 date 类型而非字符串存储日期。
    2. 字段索引控制:

      • 禁用不需要搜索的字段索引。
        • 纯展示字段。
        • 大文本日志字段。
        • 二进制数据。
        {
          "mappings": {
            "properties": {
              "log_time": {
                "type": "date",
                "index": false  // 不索引该字段
              }
            }
          }
        }
        
      • norms 控制:对不需要评分(score)的字段禁用 norms 节省空间。
        • 仅用于过滤(filter)的字段。
        • 仅用于聚合(aggregations)的字段。
        • 精确值匹配的字段(keyword)。
        • 不需要相关性评分的 text 字段。
        {
          "text_field": {
            "type": "text",
            "norms": false
          }
        }
        
    3. 文本字段优化:

      • text vs keyword:

        • 需要全文搜索:text + keyword(多字段)
        • 只需要精确匹配/聚合:仅 keyword
      • 分词器配置:

        • 选择合适的分析器(analyzer)
        • 搜索时和索引时分析器可以不同
        • 考虑自定义分析器链
      • 字段长度控制:

        • 防止过长的关键字被索引:
          • 超过指定长度的文本不被索引。
          • 减少索引大小,提高性能。
        • 控制存储开销:
          • 过长的关键字会占用大量内存,影响性能。
          • 特别对聚合、排序操作有显著影响。
        {
          "long_text": {
            "type": "text",
            "ignore_above": 1024  // 超过此长度的文本不被索引
          }
        }
        
    4. 多字段(Multi-fields)策略

      • 多种搜索方式支持:同一字段可以同时支持精确匹配和全文搜索。
      • 减少字段冗余:避免为同一数据创建多个字段,降低索引大小。
      • 支持不同的分析器:同一字段可以使用不同分析器建立多个索引。
      • 共享字段数据:多字段共享原始值,减少存储开销。
      {
        "product_name": {
          "type": "text",
          "analyzer": "ik_max_word",  // 中文分词
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            },
            "english": {
              "type": "text",
              "analyzer": "english"
            }
          }
        }
      }
      
    5. nested(嵌套)类型

      PUT /products
      {
        "mappings": {
          "properties": {
            "name": { "type": "text" },
            "reviews": {
              "type": "nested", 
              "properties": {
                "author": { "type": "keyword" },
                "rating": { "type": "float" },
                "comment": { "type": "text" }
              }
            }
          }
        }
      }
      
      • 控制嵌套深度:
        • 避免多层嵌套(建议不超过3层)。
        • 嵌套层级过深会显著增加查询复杂度。
      • 限制数组大小:
        • 单个文档的嵌套对象数量不宜过多(通常<100)。
        • 大数组会明显影响性能。
      • 与父子关系的比较
        特性nested类型父子关系
        数据模型一对少量,强关联一对多量,弱关联
        性能特点查询快,写入成本高写入快,查询成本较高
        适用场景对象少且频繁共同查询对象多且需要独立更新
        内存消耗较高较低
    6. 其他优化技巧

      • copy_to 合并字段:创建自定义的"超级字段"。
        • 搜索简化:无需构建复杂的多字段查询,单字段搜索替代多个should子句。
        • 性能优化:减少查询解析时间,避免昂贵的跨字段查询(如multi_match)。
        • 灵活性:为组合字段单独配置分析器,不影响原始字段的独立使用。
        {
          "first_name": {
            "type": "text",
            "copy_to": "full_name" 
          },
          "last_name": {
            "type": "text",
            "copy_to": "full_name"
          },
          "full_name": {
            "type": "text"
          }
        }
        
      • doc_values 控制:对不需要排序/聚合的字段禁用
        {
          "session_data": {
            "type": "keyword",
            "doc_values": false
          }
        }
        
      • index_options:控制倒排索引中存储的内容(docs/freqs/positions/offsets)
        • docs (最基本)
          • 只索引文档是否存在。
          • 适用于仅需判断文档是否匹配的场景。
          • 不支持位置查询、高亮等高级功能。
        • freqs (文档+词频)
          • 记录文档和词项频率。
          • 支持相关性评分(TF-IDF)。
          • 仍不支持位置查询。
        • positions (文档+词频+位置) - 默认值
          • 记录文档、词频和词项位置。
          • 支持短语查询、位置查询和高亮。
          • 大多数全文搜索场景的推荐设置。
        • offsets (文档+词频+位置+偏移量)
          • 记录文档、词频、位置和字符偏移。
          • 支持高亮显示时需要此选项。
          • 索引体积最大,性能开销最高。
        • 性能与存储影响
          选项索引大小查询性能功能支持
          docs最小最快仅匹配
          freqs匹配+评分
          positions中等中等匹配+评分+短语查询
          offsets最大最慢匹配+评分+短语查询+高亮
  2. 索引生命周期管理

    1. 阶段配置优化

      • 热阶段(Hot)精细化配置
        "hot": {
          "actions": {
            "rollover": {
              "max_primary_shard_size": "50gb",  // 更精确的主分片大小控制
              "max_age": "24h",                 // 根据写入速率调整
              "max_docs": 20000000              // 基于文档体积设定
            },
            "shrink": {                         // 热阶段预收缩
              "number_of_shards": 3             // 保留适当分片数平衡吞吐
            },
            "set_priority": {
              "priority": 100                   // 确保热索引高优先级
            }
          }
        }
        
        • 优化要点:
          • 使用max_primary_shard_size替代max_size实现分片均衡。
          • 根据业务高峰时段调整max_age避免集中滚动。
          • 热阶段预收缩减少后续温阶段压力。
      • 温阶段(Warm)性能优化
        "warm": {
          "min_age": "12h",                    // 根据查询模式调整
          "actions": {
            "allocate": {
              "number_of_replicas": 1,         // 温数据保留1副本
              "require": {
                "data": "warm",
                "disk_type": "hdd"             // 明确存储类型
              }
            },
            "forcemerge": {
              "max_num_segments": 3,           // 不完全合并为1,平衡IO压力
              "index_codec": "best_compression" // 启用压缩
            },
            "readonly": {}                     // 确保只读
          }
        }
        
        • 优化要点:
          • 分阶段执行forcemerge(先合并到10段,再合并到3段)。
          • 采用best_compression编码节省30%存储空间。
          • 设置min_age避免过早迁移影响查询。
      • 冷阶段(Cold)存储优化
        "cold": {
          "min_age": "30d",
          "actions": {
            "allocate": {
              "require": {
                "data": "cold",
                "storage": "object"           // 对象存储标识
              }
            },
            "searchable_snapshot": {         // 可搜索快照
              "snapshot_repository": "s3-repo",
             "force_merge_index": true       // 快照前强制合并
            },
           "unfollow": {}                   // 解除CCR跟随
          }
        }
        
        • 优化要点:
          • 与对象存储(S3/OBS)深度集成。
          • 冷索引采用searchable_snapshot+force_merge组合。
          • 对于CCR索引自动解除跟随关系。
    2. 存储分层优化

      • 热数据层配置
        # elasticsearch.yml
        node.roles: [ data_hot, ingest ]
        node.attr.storage_tier: "hot_ssd"
        path.data: /opt/elasticsearch/hot_data  # SSD存储路径
        
      • 温数据层配置
        node.roles: [ data_warm ]
        node.attr.storage_tier: "warm_hdd"
        path.data: /opt/elasticsearch/warm_data # HDD存储路径
        
      • 冷数据层对象存储集成
        PUT _snapshot/s3-repository
        {
          "type": "s3",
          "settings": {
            "bucket": "my-es-cold-data",
            "endpoint": "s3.ap-east-1.amazonaws.com",
            "base_path": "indices/",
            "chunk_size": "1gb",
            "max_restore_bytes_per_sec": "200mb"
          }
        }
        

三、查询性能优化

  1. 使用过滤器(filter)替代查询(query)
    • filter结果可缓存,避免评分计算。
      GET /orders/_search
      {
        "query": {
          "bool": {
            "must": [
              { "match": { "product": "laptop" } }
            ],
            "filter": [  // 不计算相关性的过滤条件
              { "range": { "price": { "gte": 1000 } } },
              { "term": { "status": "completed" } }
            ]
          }
        }
      }
      
  2. 避免深度分页
    • 深度分页使用search_after代替from+size。
      {
        "size": 10,
        "sort": ["_doc"],
        "search_after": [12345]  // 使用search_after代替from+size
      }
      
  3. 字段选择性加载
    • 通过 _source 控制必要的返回字段。
      GET /products/_search
      {
        "_source": ["name", "price"],  // 只返回必要字段
        "query": { ... }
      }
      
  4. 使用异步搜索
    • 对于复杂查询且对实时性要求不高。
      POST /sales/_async_search
      {
        "query": { ... },
        "size": 100
      }
      
  5. 查询结果缓存
    • 启用后自动缓存查询结果。
      PUT /my_index/_settings
      {
        "index.requests.cache.enable": true
      }
      
  6. 合理使用doc_values
    • doc_values列式存储比fielddata更高效,内存占用更低。
      PUT /products
      {
        "mappings": {
          "properties": {
            "category": {
              "type": "keyword",  // keyword类型默认启用doc_values
              "doc_values": true  // 显式启用确保可用
            }
          }
        }
      }
      
  7. 限制聚合桶数量
    • 可以减少计算和网络传输开销。
      GET /sales/_search
      {
        "aggs": {
          "top_categories": {
            "terms": {
              "field": "category.keyword",
              "size": 10  // 限制返回桶数量
            }
          }
        }
      }
      
  8. 使用近似聚合
    • 大数据集去重计数,牺牲精确性换取性能。
      GET /logs/_search
      {
        "aggs": {
          "unique_visitors": {
            "cardinality": {
              "field": "user_id.keyword",
              "precision_threshold": 100  // 精度控制
            }
          }
        }
      }
      
  9. 分层采样聚合
    • 大数据集探索性分析。
      GET /events/_search
      {
        "aggs": {
          "sampled": {
            "sampler": {
              "shard_size": 200  // 每分片采样数量
            },
            "aggs": {
              "keywords": {
                "significant_terms": {
                  "field": "message.keyword"
                }
              }
            }
          }
        }
      }
      

四、写入性能优化

  1. 写入配置优化

    • 调整刷新间隔:默认1s,增大可减少刷新开销,批量导入数据时可临时设置为-1(禁用刷新)。
      PUT /logs/_settings
      {
        "index.refresh_interval": "30s"  // 默认1s,增大可减少刷新开销
      }
      
    • 禁用暂时不需要的功能:提高写入速度,写入完成后恢复配置。
      PUT /temp_data
      {
        "settings": {
          "index.number_of_replicas": 0,
          "index.refresh_interval": "-1",
          "index.translog.durability": "async"  // 异步写事务日志
        },
        "mappings": {
          "dynamic": false,  // 禁用动态映射
          "properties": {...}
        }
      }
      
  2. 使用 Bulk API 批量写入

    POST _bulk
    { "index" : { "_index" : "logs", "_id" : "1" } }
    { "timestamp": "2023-01-01T00:00:00", "message": "test" }
    { "create" : { "_index" : "logs", "_id" : "2" } }
    { "timestamp": "2023-01-01T00:00:01", "message": "test2" }
    

    最佳实践:

    • 单批次5-15MB数据
    • 每批1000-5000个文档
    • 多线程并发发送(3-5个线程)
  3. 使用Indexing Buffer调优

    • index_buffer_size 默认10%,可适当增加JVM堆的堆内存占比。
      PUT _cluster/settings
      {
        "persistent": {
          "indices.memory.index_buffer_size": "20%"  // 默认10%,可适当增加
        }
      }
      

五、硬件与系统优化

  1. 硬件配置建议

    • 内存:数据节点至少64GB,堆内存不超过32GB
    • 磁盘:使用SSD,RAID 0配置
    • CPU:16核以上
    • 网络:10Gbps或更高带宽
  2. JVM配置

    # jvm.options
    -Xms16g  # 堆内存最小值
    -Xmx16g  # 堆内存最大值,不超过物理内存50%
    -XX:+UseG1GC
    
  3. 操作系统优化

    • Linux内核参数:
      # 增加文件描述符限制
      echo "* - nofile 655350" >> /etc/security/limits.conf
      
      # 虚拟内存配置
      echo "vm.max_map_count=262144" >> /etc/sysctl.conf
      sysctl -p
      
      # 禁用swap
      swapoff -a
      echo "vm.swappiness = 1" >> /etc/sysctl.conf
      

六、集群层面优化

  1. 集群规划与配置
    • 节点角色分离:
      • 专用主节点:node.master: true, node.data: false
      • 专用数据节点:node.master: false, node.data: true
      • 专用协调节点:node.master: false, node.data: false
    • 优化建议:
      • 生产集群至少3个专用master节点
      • 大数据集群分离data和ingest节点
  2. 分片策略优化
    • 合理设置分片大小和数量:
      • 每个分片大小建议在10-50GB之间
      • 分片总数 = 节点数 × 每节点最大分片数(建议不超过1000)
      PUT /logs
      {
        "settings": {
          "number_of_shards": 10,          // 根据数据量决定
          "number_of_replicas": 1,         // 生产环境至少1个
          "index.routing.allocation.total_shards_per_node": 2  // 控制每节点分片数
        }
      }
      
    • 冷热数据分层
      PUT _ilm/policy/hot_warm_policy
      {
        "policy": {
          "phases": {
            "hot": {
              "actions": {
                "rollover": { "max_size": "50GB" },
                "set_priority": { "priority": 100 }
              }
            },
            "warm": {
              "min_age": "7d",
              "actions": {
                "forcemerge": { "max_num_segments": 1 },
                "shrink": { "number_of_shards": 1 },
                "allocate": { "require": { "data": "warm" } }
              }
            }
          }
        }
      }
      

七、监控与维护

  1. 关键监控指标
    # 集群健康
    GET _cluster/health
    
    # 节点状态
    GET _nodes/stats
    
    # 热点线程
    GET _nodes/hot_threads
    
    # 磁盘使用
    GET _cat/allocation?v
    
  2. 定期维护操作
    # 强制合并段(只读索引)
    POST /logs-2023-01/_forcemerge?max_num_segments=1
    
    # 清理缓存
    POST /_cache/clear
    
    # 分片重平衡
    PUT _cluster/settings
    {
      "persistent": {
        "cluster.routing.rebalance.enable": "all"
      }
    }
    
  3. 安全与稳定性
    • 关键安全配置
      # elasticsearch.yml
      xpack.security.enabled: true
      xpack.security.transport.ssl.enabled: true
      
    • 熔断器设置
      PUT _cluster/settings
      {
        "persistent": {
          "indices.breaker.total.limit": "70%",
          "network.breaker.inflight_requests.limit": "80%"
        }
      }
      
  4. 灾难恢复策略
    • 快照备份配置
      PUT _snapshot/my_backup
      {
        "type": "fs",
        "settings": {
          "location": "/mnt/backups/es_backups",
          "max_snapshot_bytes_per_sec": "50mb",
          "max_restore_bytes_per_sec": "50mb"
        }
      }
      
      # 创建快照
      PUT _snapshot/my_backup/snapshot_1?wait_for_completion=true
      {
        "indices": "*",
        "ignore_unavailable": true,
        "include_global_state": false
      }
      
    • 跨集群复制(CCR)
      PUT /_ccr/follow/logs-follower
      {
        "remote_cluster": "remote-cluster",
        "leader_index": "logs-leader",
        "max_read_request_operation_count": 5120,
        "max_outstanding_read_requests": 12
      }
      

http://www.kler.cn/a/611624.html

相关文章:

  • 【Lua】一文快速掌握 Lua 语言指令(Lua 备忘清单)
  • 直播预告 | TDgpt 智能体发布 时序数据库 TDengine 3.3.6 发布会即将开启
  • 【第30节】MFC编程:ListCtrl控件和TreeCtrl控件
  • SPI协议(20250325)
  • HarmonyOS:统一拖拽
  • 关于 K8s 的一些基础概念整理-补充
  • 交换机及其作用详解
  • [RITSEC CTF 2025] Crypto
  • vscode 通过Remote-ssh远程连接服务器报错 could not establish connection to ubuntu
  • 使用react 引入相对路径文件
  • 学习日记0327
  • xxljob阻塞处理策略设置为单机串行导致的bug
  • PyTorch 深度学习实战(22):多智能体强化学习(MARL)
  • 堆的常见应用2
  • 3.27【A】cv homework
  • 手撕LRU缓存Java版(带输入输出)
  • 《基于机器学习发电数据电量预测》开题报告
  • 学习本地部署DeepSeek的过程(基于LM Studio)
  • 自然语言处理|金融舆情解析:智能事件抽取与风险预警之道
  • 算法-动态规划三