首页 > 其他分享 >ES调优建议

ES调优建议

时间:2024-11-13 11:43:59浏览次数:1  
标签:index 建议 索引 写入 查询 source 调优 构建 ES

查询模块

保证ES节点有充足的内存

ES默认分配节点一半的内存给JVM(最多会分配30GB),剩余的内存用于向量索引和pagecache,节点内存不足会导致频繁触发向量索引的驱逐和加载,导致查询延迟较高。

因此需要确保数据节点有足够的内存,使向量索引常驻内存。可以通过以下方式获取节点向量数据的内存使用情况。

GET /_bpack/_knn/stats
GET /_bpack/_knn/nodeId1,nodeId2/stats // 获取指定节点nodeId1,nodeId2的内存使用情况,使用逗号进行分割

如果发现内存不足,建议参考资源评估建议进行集群容量规划

首次查询之前把数据进行预加载

默认情况下,ES的向量索引构建完成后,不会主动加载到内存中。并且在首次查询中会触发加载,只有向量数据全部加载到内存中才能进行查询。

在首次查询前,可以通过如下指令提前预热数据,降低延迟:

GET /_bpack/_knn/warmup/my_index1, my_index2

尽量减少segment的数量

ES中的索引的基础存储单元为segment。在KNN算法中,每个segment都会单独构建向量索引,因此在搜索过程中需要检索每个segment

如果索引中segment的划分过于琐碎,会影响检索的速度。一般情况下,可以通过BES的定时任务,定期把琐碎的segment合并。

当然也可以在写入结束后的业务低峰期,通过force_merge强制执行合并,减少segment的数量,提高检索的效率。

POST /my-index-000001/_forcemerge?max_num_segments=3

尽量避免从_source中查询向量字段

在构建索引过程中默认会把原始JSON存储在_source字段中,因此搜索结果中的每一次命中索引都包含完整的_source内容。

当索引包含高维度向量字段时,_source可能比较大,加载成本就很高,这可能会显著降低KNN搜索的速度。

尽量使用doc_value存储数据

doc_value_source存储的内容是一致的,但是doc_value是面向列式存储的,因此会拥有更好的排序和聚合效率。

创建索引过程中,不需要特地打开 doc_value 开关,ES对于绝大多数类型的数据会自动构建 doc_value 。

对于 text 类型的数据,不会构建 doc_value 而是存储在 _source 中。
因此如果可以的话,建立索引过程中尽量使用 keyword 类型代替 text 类型。

查询过程中,可以指定查询doc_value中字段,减少加载_source数据,加速查询效率。

查询方式如下所示:

 
GET /my_index/_search
{
  "query": {
    "hnsw": {
      "vec": {
        "vector": [
          0.495662,
          
          ...
         
          -0.10869
        ],
        "k": 10,
        "ef": 200
      }
    }
  },
  "size": 10,
  "_source":false, // 规避加载 _source 中的数据,加速查询效率
  "docvalue_fields":[
    "id",
    "tag_keyword"
  ] // 填写需要从 doc_value 中查询的字段
}

关闭默认的自动构建mapping开关

对于字符串类型的字段,自动构建的mapping会默认同时构建textkeyword类型数据,比较浪费磁盘空间。 如果不需要对字段进行全文检索,则只需要设置keyword类型即可。

也可以通过下面配置,设置默认构建单一类型:

 
PUT index
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

规避使用_source存储数据,减少查询过程中的数据加载量

在构建索引的过程中,可以通过如下方式禁用_source字段:

 
PUT my-index-000001
{
  "mappings": {
    "_source": {
      "enabled": false
    }
  }
}

但是禁用_source的操作需要您深思熟虑后进行,因为禁用_source后以下功能将无法使用

  • 无法使用updateupdate_by_query以及reindex的API,也无法从一个集群的索引reindex到另一个集群
  • 无法使用高亮
  • 不能修改索引的mappingsanalysis

也可以对向量字段不构建_source,只对标量字段构建

 
PUT my-index-000001
{
  "mappings": {
    "_source": {
      "excludes": [
        "vec",  // 可以直接指定不构建_source的字段
        "vec.*" // 也可以通过通配符进行模糊匹配
      ]
    }
  }
}

写入模块

合理配置shard数量

为了使shard分配的更加均匀,从而避免写入热点,建议把shard数量设置成节点数量的整数倍。

shard数量设置方法如下所示:

 
PUT /my_index
{
  "settings": {
    "index": {
      "number_of_shards": 3 // 索引的分片数量,创建后无法修改。
    }
  }
}

合理设置replica的数量

没有副本意味着节点丢失可能会导致数据丢失,因此多副本对于数据安全十分重要,以便在出现问题时可以重新加载数据。

并且适度增加副本数量,可以增大查询过程中的并行程度,从而提高查询效率。

每增加一个副本都会增加集群磁盘成本,并且副本数不能大于节点的数量。

 
在多副本情况下,写入过程可以先设置副本数 index.number_of_replicas 为0,增加写入的速度。
PUT /my_index/_settings
{
  "number_of_replicas": 0 // 分片的副本数量,取值范围[0, 节点数-1],可随时修改
}
在写入完成后,再把副本调整到合适的数量。

合理调整refresh间隔

refresh_interal是用来控制多久把内存里的数据刷出segment的。ES会对刷出的segment进行合并,如果合并不过来会阻止写入。

所以把refresh_interval调大,也可以把刷出的segment变大,降低合并的频率,提升导入性能。

调整refresh_interval方式如下:

 
PUT /my_index/_settings
{
 	"index.refresh_interval": "10s"
}

写入速度流程优化

使用bulk请求写入数据

bulk请求写入效率比单个索引请求性能更好,尽量使用bulk请求进行数据写入。

为了知道批量请求的最佳大小,可以在具有单index的单节点集群进行上进行测试。
首先尝试一个批次包含100个document,之后测试一个批次包含200个,以此类推,在每次测试过程中将批量请求中的document数量增加一倍。
当索引构建的速度开始趋于平稳时,批量请求需要包含的document数据就达到了的最佳大小。
增加索引构建并发

当构建较大数据量的向量索引时,可能会出现build较慢的情况。 可以根据分片数和节点CPU核数,在写入数据前适当调整"bpack.knn.hnsw.index_thread_qty" 。

例如,1kw数据量,1节点2分片,节点为16核CPU,我们可以把"bpack.knn.hnsw.index_thread_qty" 设置为4-6(如果设置为8,会使CPU满载,生产环境可能有风险),可以提高构建索引效率。

调节方式如下:

 
PUT /_cluster/settings
{
    "persistent" : {
        "bpack.knn.hnsw.index_thread_qty":3
    }
}

"bpack.knn.hnsw.index_thread_qty" 参数设置偏大,会导致构建时启动线程过多。在负载比较高的集群,不建议调整这个参数,以免集群满载。

如果写入和构建向量索引偏慢,可以通过临时减少集群负载(减少其他写入和查询),并调大"bpack.knn.hnsw.index_thread_qty"的方式来加快构建 ,等到构建结束,再将"bpack.knn.hnsw.index_thread_qty" 调整回1。

自动生成DocumentID

当写入索引过程中指定 _id 时,ES需要检查同一分片中是否已存在具有相同 _id 的document,这是一项成本高昂的操作,并且随着索引的增长,成本会变得更高。

如果使用场景允许,建议写入过程中不指定_id, ES可以跳过检查,从而加快索引速度。

 
POST _bulk
{ "create" : { "_index" : "test1"} }  // 不指定 _id
{ "create" : { "_index" : "test2", "_id" : "3" } } // 指定 _id
    <iframe style="display: none !important"></iframe>

标签:index,建议,索引,写入,查询,source,调优,构建,ES
From: https://www.cnblogs.com/ExMan/p/18543579

相关文章

  • Educational Codeforces Round 157 (Rated for Div. 2) - VP 记录
    Preface啊啊啊为什么我老是被简单题卡啊!A.TreasureChestA题题面这么长吓我一跳。分类讨论,钥匙在前面可以拿了钥匙直接到箱子那里;箱子在前面就尽量把箱子往钥匙搬,让折回的距离尽量小。点击查看代码#include<cstdio>#include<algorithm>usingnamespacestd;intmain......
  • Serverless GPU:助力 AI 推理加速
    本文整理自2024云栖大会,阿里云智能集团高级技术专家聂大鹏、NVIDIA解决方案架构师金国强演讲议题《ServerlessGPU:助力AI推理加速》近年来,AI技术发展迅猛,企业纷纷寻求将AI能力转化为商业价值,然而,在部署AI模型推理服务时,却遭遇成本高昂、弹性不足及运维复杂等挑战。本文......
  • HyperWorks的shrink warp meshing
    在HyperWorks中,针对某些具有复杂几何特征的零部件的网格剖分,AltairHyperMesh向用户提供了一种名为ShrinkWarpMeshing的技术,快捷高效地完成有限元模型前处理工作。例如在车辆碰撞分析研究中,用户可以使用ShrinkWarpMeshing技术快速构建诸如传动系统等(具有复杂几何特征且非......
  • 【小程序】封装网络请求request模块
    一、封装request请求因为我把所有项目中的接口也封装到了一个文件中,所以我建了一个services的文件夹,在下面建了一个request.js在这个里面做了请求拦截器和响应拦截器,constapiConfig=require('../config/baseUrl.js');classhttpClient{prefixUrl='';const......
  • Codeforces Round 985 div1+2 个人题解(A~E)
    CodeforcesRound985div1+2个人题解(A~E)Dashboard-Refact.aiMatch1(CodeforcesRound985)-Codeforces火车头#include<bits/stdc++.h>usingnamespacestd;#defineftfirst#definesdsecond#defineyescout<<"yes\n"#definenoc......
  • Principles of Distributed Ledgers
    PrinciplesofDistributedLedgers:CourseworkObjectiveTheobjectiveofthiscourseworkistodevelopaSoliditycontract,HumanResources,whichimplementsahumanresources(HR)paymentsystemandtodeployitonOptimism.Thiscontractwillenableahum......
  • 微信小程序 - 解决报错{“errno“:600001,“errMsg“:“request:fail errcode:-202cronet_
    前言关于此问题网上的教程都无法解决,如果您的报错信息与我相似,即可解决。在微信小程序开发中,详细解决小程序请求接口报错:{“errno”:600001,“errMsg”:“request:failerrcode:-202cronet_error_code:-202error_msg:net::ERR_CERT_AUTHORITY_INVALID”},微信小程序发起网络请求......
  • ES6常见语法详解
    原文链接:ES6常见语法详解–每天进步一点点0.什么是ES6ES的全称是ECMAScript,它是由ECMA国际标准化组织,制定的一项脚本语言的标准化规范。ES6实际上是一个泛指,泛指ES2015及后续的版本。1.let、const、var的区别let是es6中新增的语法let只对当前区块定义有效:......
  • Freesql、SqlSugar测试有感
    突然心血来潮测试了一下Freesql和SqlSugar的批量插入和批量更新性能,一搜测评一大堆,但是没找到自己想要的结果,自己动手测试一下基本的批量插入和批量更新性能。废话不多说直接贴代码1usingFreeSql;2usingFreeSql.DataAnnotations;3usingSqlSugar;45namesp......
  • Introspect M5513-DDR5 MR-DIMM Module Test System
    M5513DDR5MR-DIMMModuleTestSystemComplete ChaaracterizationandFuncationalTestingofMR-DIMMModulesTheM5513isanall-inclusivememorytestsystemfornext-generationDDR5multiplexed-rankdualinline memorymodules(MR-DIMM).Operating......