性能调优

更新时间:
复制 MD 格式

本文介绍PolarDB-X智能搜索在索引设计、写入和查询方面的性能优化建议。

索引设计优化

分片数量规划

分片(Shard)是数据分布和并行处理的基本单元,合理规划分片数量对性能至关重要。

数据量

建议分片数

说明

< 10 GB

1

单分片即可,避免过度分片带来的开销。

10 GB ~ 50 GB

2-3

适度分片,平衡查询并行度和管理成本。

50 GB ~ 200 GB

3-5

确保单分片 30-50 GB。

> 200 GB

按每分片 30-50 GB 计算

避免单分片过大影响查询延迟。

关键原则:

  • 每个分片建议保持在 30-50 GB 之间。

  • 分片数量不宜超过节点数 × 20。

  • 分片数在索引创建后不可修改,需提前规划。

  • 过多分片会增加集群元数据开销和协调成本。

副本数量选择

场景

副本数

说明

开发测试

0

节省资源,不需要高可用。

标准生产

1

保证高可用,可容忍 1 节点故障。

高可用要求

2

允许同时失去 2 个节点。

读密集型场景

1-2

副本可分担读请求。

说明

副本数可随时动态调整,无需重建索引。

Mapping 设计最佳实践

curl -XPUT "http://<Search引擎地址>:<port>/my-index" \
  -u "<用户名>:<密码>" -k \
  -H "Content-Type: application/json" \
  -d '{
    "settings": { "index.mapping.total_fields.limit": 1000 },
    "mappings": {
      "dynamic": "strict",
      "properties": {
        "title":      { "type": "text",    "analyzer": "ik_max_word" },
        "status":     { "type": "keyword" },
        "price":      { "type": "float" },
        "created_at": { "type": "date" }
      }
    }
  }'
  • 设置 "dynamic": "strict" 禁止自动添加未定义字段,避免 mapping 膨胀。

  • 不需要搜索的字段设置 "index": false 减少索引开销。

  • 不需要聚合/排序的 text 字段不要添加 keyword 子字段。

  • 精确匹配字段使用 keyword 而非 text

  • 数值字段选择合适的类型(不要所有数字都用 long)。

禁用不必要的特性

配置

作用

何时禁用

norms: false

禁用长度归一化因子

不需要按相关度排序的字段

doc_values: false

禁用列式存储

不需要排序/聚合的字段

index: false

不建立索引

只需要存储不需要搜索的字段

store: false

不单独存储

已在 _source 中,无需额外存储

写入性能优化

批量写入配置

  • 单次 _bulk 大小:5-15 MB,过大会导致内存压力。

  • 单次文档数:1000-5000 条,取决于单条文档大小。

  • 并发写入线程:2-4,根据节点 CPU 核数调整。

写入期间索引配置优化

大批量导入数据前,临时调整索引参数以提升写入速度:

# 写入前:关闭副本、增大 refresh 间隔
curl -XPUT "http://<Search引擎地址>:<port>/my-index/_settings" \
  -u "<用户名>:<密码>" -k \
  -H "Content-Type: application/json" \
  -d '{
    "number_of_replicas":            0,
    "refresh_interval":              "-1",
    "translog.durability":           "async",
    "translog.flush_threshold_size": "1gb"
  }'

# === 执行批量数据导入 ===

# 写入后:恢复正常配置
curl -XPUT "http://<Search引擎地址>:<port>/my-index/_settings" \
  -u "<用户名>:<密码>" -k \
  -H "Content-Type: application/json" \
  -d '{
    "number_of_replicas":  1,
    "refresh_interval":    "1s",
    "translog.durability": "request"
  }'

curl -XPOST "http://<Search引擎地址>:<port>/my-index/_refresh"                        -u "<用户名>:<密码>" -k
curl -XPOST "http://<Search引擎地址>:<port>/my-index/_forcemerge?max_num_segments=1"  -u "<用户名>:<密码>" -k

查询性能优化

避免深度分页

// 不推荐:深度分页性能极差
{ "from": 10000, "size": 10 }

// 推荐:使用 search_after
{
  "size": 10,
  "sort": [ { "created_at": "desc" }, { "_id": "asc" } ],
  "search_after": ["2025-05-25T10:00:00Z", "doc_id_123"]
}

合理使用 filter context

filter 子句不参与评分,可利用缓存,性能优于 must。不需要影响相关度评分的条件,一律放在 filter 中。

限制返回字段

{
  "query": { "match": { "content": "搜索" } },
  "_source": ["title", "summary", "created_at"],
  "size": 10
}

避免返回大型字段(如全文 content、向量 embedding),只返回展示所需的字段。

避免昂贵查询

  • *abc 前缀通配符:使用 reverse token filterngram

  • 复杂 script_score:使用预计算字段。

  • 嵌套层级过深的nested query:反范式化设计。

  • 大量should子句 (>100):使用terms query

  • match_all + 大size:分页或scroll

向量检索优化

向量维度选择

模型

维度

内存/百万文档

适用场景

小型模型

128-256

~0.5-1 GB

推荐/分类等轻量场景

通用模型

768

~3 GB

通用语义搜索

大型模型

1024-1536

~4-6 GB

高精度语义/多模态

HNSW 参数调优

参数

默认

说明

ef_construction

100

建议 128-512,提高精度但增加索引时间

m

16

建议 8-32,每节点最大连接数

ef_search

100

通过查询参数动态设置

监控关键指标

# 节点资源使用
curl -XGET "http://<Search引擎地址>:<port>/_cat/nodes?v&h=name,heap.percent,ram.percent,cpu,disk.used_percent" \
  -u "<用户名>:<密码>" -k

# 线程池(关注 rejected)
curl -XGET "http://<Search引擎地址>:<port>/_cat/thread_pool?v&h=node_name,name,active,queue,rejected" \
  -u "<用户名>:<密码>" -k

性能告警阈值参考:

  • CPU 使用率 > 80% 警告 / > 90% 严重:需要扩容或优化查询。

  • 磁盘使用率 > 75% 警告 / > 85% 严重:磁盘满会导致索引只读。