Elasticsearch 优化是一个系统工程,需要根据实际业务场景、数据特点和查询模式进行针对性调整。关键优化方向包括:
索引结构优化
数据类型选择优化:
字段索引控制:
{
"mappings": {
"properties": {
"log_time": {
"type": "date",
"index": false // 不索引该字段
}
}
}
}
{
"text_field": {
"type": "text",
"norms": false
}
}
文本字段优化:
text vs keyword:
分词器配置:
字段长度控制:
{
"long_text": {
"type": "text",
"ignore_above": 1024 // 超过此长度的文本不被索引
}
}
多字段(Multi-fields)策略
{
"product_name": {
"type": "text",
"analyzer": "ik_max_word", // 中文分词
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
nested(嵌套)类型
PUT /products
{
"mappings": {
"properties": {
"name": { "type": "text" },
"reviews": {
"type": "nested",
"properties": {
"author": { "type": "keyword" },
"rating": { "type": "float" },
"comment": { "type": "text" }
}
}
}
}
}
特性 | nested类型 | 父子关系 |
---|---|---|
数据模型 | 一对少量,强关联 | 一对多量,弱关联 |
性能特点 | 查询快,写入成本高 | 写入快,查询成本较高 |
适用场景 | 对象少且频繁共同查询 | 对象多且需要独立更新 |
内存消耗 | 较高 | 较低 |
其他优化技巧
{
"first_name": {
"type": "text",
"copy_to": "full_name"
},
"last_name": {
"type": "text",
"copy_to": "full_name"
},
"full_name": {
"type": "text"
}
}
{
"session_data": {
"type": "keyword",
"doc_values": false
}
}
选项 | 索引大小 | 查询性能 | 功能支持 |
---|---|---|---|
docs | 最小 | 最快 | 仅匹配 |
freqs | 小 | 快 | 匹配+评分 |
positions | 中等 | 中等 | 匹配+评分+短语查询 |
offsets | 最大 | 最慢 | 匹配+评分+短语查询+高亮 |
索引生命周期管理
阶段配置优化
"hot": {
"actions": {
"rollover": {
"max_primary_shard_size": "50gb", // 更精确的主分片大小控制
"max_age": "24h", // 根据写入速率调整
"max_docs": 20000000 // 基于文档体积设定
},
"shrink": { // 热阶段预收缩
"number_of_shards": 3 // 保留适当分片数平衡吞吐
},
"set_priority": {
"priority": 100 // 确保热索引高优先级
}
}
}
"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": {} // 确保只读
}
}
"cold": {
"min_age": "30d",
"actions": {
"allocate": {
"require": {
"data": "cold",
"storage": "object" // 对象存储标识
}
},
"searchable_snapshot": { // 可搜索快照
"snapshot_repository": "s3-repo",
"force_merge_index": true // 快照前强制合并
},
"unfollow": {} // 解除CCR跟随
}
}
存储分层优化
# 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"
}
}
GET /orders/_search
{
"query": {
"bool": {
"must": [
{ "match": { "product": "laptop" } }
],
"filter": [ // 不计算相关性的过滤条件
{ "range": { "price": { "gte": 1000 } } },
{ "term": { "status": "completed" } }
]
}
}
}
{
"size": 10,
"sort": ["_doc"],
"search_after": [12345] // 使用search_after代替from+size
}
GET /products/_search
{
"_source": ["name", "price"], // 只返回必要字段
"query": { ... }
}
POST /sales/_async_search
{
"query": { ... },
"size": 100
}
PUT /my_index/_settings
{
"index.requests.cache.enable": true
}
PUT /products
{
"mappings": {
"properties": {
"category": {
"type": "keyword", // keyword类型默认启用doc_values
"doc_values": true // 显式启用确保可用
}
}
}
}
GET /sales/_search
{
"aggs": {
"top_categories": {
"terms": {
"field": "category.keyword",
"size": 10 // 限制返回桶数量
}
}
}
}
GET /logs/_search
{
"aggs": {
"unique_visitors": {
"cardinality": {
"field": "user_id.keyword",
"precision_threshold": 100 // 精度控制
}
}
}
}
GET /events/_search
{
"aggs": {
"sampled": {
"sampler": {
"shard_size": 200 // 每分片采样数量
},
"aggs": {
"keywords": {
"significant_terms": {
"field": "message.keyword"
}
}
}
}
}
}
写入配置优化
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": {...}
}
}
使用 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" }
最佳实践:
使用Indexing Buffer调优
PUT _cluster/settings
{
"persistent": {
"indices.memory.index_buffer_size": "20%" // 默认10%,可适当增加
}
}
硬件配置建议
JVM配置
# jvm.options
-Xms16g # 堆内存最小值
-Xmx16g # 堆内存最大值,不超过物理内存50%
-XX:+UseG1GC
操作系统优化
# 增加文件描述符限制
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
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" } }
}
}
}
}
}
# 集群健康
GET _cluster/health
# 节点状态
GET _nodes/stats
# 热点线程
GET _nodes/hot_threads
# 磁盘使用
GET _cat/allocation?v
# 强制合并段(只读索引)
POST /logs-2023-01/_forcemerge?max_num_segments=1
# 清理缓存
POST /_cache/clear
# 分片重平衡
PUT _cluster/settings
{
"persistent": {
"cluster.routing.rebalance.enable": "all"
}
}
# 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%"
}
}
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
}
PUT /_ccr/follow/logs-follower
{
"remote_cluster": "remote-cluster",
"leader_index": "logs-leader",
"max_read_request_operation_count": 5120,
"max_outstanding_read_requests": 12
}