Elasticsearch搜索调优权威指南 (1/3)

简介: Elasticsearch搜索调优权威指南,是QBOX在其博客上发布的系列文章之一,本文是该系列的第一篇,主要从文档建模、内存分配、文件系统缓存、GC和硬件等方面介绍了优化查询性能的一些经验。

英文原文:https://qbox.io/blog/elasticsearch-search-tuning-5-0-ultimate-guide
作者:Adam Vanderbush
译者:杨振涛

目录

  1. 文档建模
  2. 全局序列号和延迟
  3. 多代关系
  4. 为文件系统缓存分配内存

Elasticsearch搜索调优权威指南,是QBOX在其博客上发布的系列文章之一,本文是该系列的第一篇,主要从文档建模、内存分配、文件系统缓存、GC和硬件等方面介绍了优化查询性能的一些经验。

Elasticsearch 5.0.0确实是在2.x之后的一个大版本,为大家带来了许多新东西。Elasticsearch现在作为Elastic Stack中的一员,与整个技术栈的其他产品的版本号已经对齐,现在Kibana、Logstash、Beats和Elasticsearch全都是5.0版本了。

这个版本的Elasticsearch是目前为止最快、最安全、最弹性,也是最易用的,而且还带来了很多的改进和新特性。

我们已经通过“Elasticsearch性能调优权威指南”系列,介绍了一些性能调优的基本经验和方法,解释了每一步最关键的系统设置和衡量指标。该系列共分下列3个部分:

  • The Authoritative Guide to Elasticsearch Performance Tuning (Part 1) 
  • The Authoritative Guide to Elasticsearch Performance Tuning (Part 2) 
  • The Authoritative Guide to Elasticsearch Performance Tuning (Part 3)

索引决策也很重要,它对如何搜索数据有很大的影响。如果是一个字符串字段,是否需要分词或归一化?如果是,怎么做?如果是一个数值型属性,需要哪种精度?还有很多其他类型,比如date-time、geospatial shape以及父子关系等,需要更多特别的考虑。

我们也通过一个系列教程讨论了“Elasticsearch索引性能优化”,介绍了一些通用的技巧和方法,来最大化索引的吞吐量并降低监控和管理的负载。该教程分如下3个部分:

  • How to Maximize Elasticsearch Indexing Performance (Part 1) 
  • How to Maximize Elasticsearch Indexing Performance (Part 2) 
  • How to Maximize Elasticsearch Indexing Performance (Part 3)

本文旨在推荐一些搜索调优技术、策略以及Elasticsearch 5.0及以上的推荐特性。

1.文档建模

内部对象属性数组并不像期望的那样工作。Lucene 中没有内部对象的概念,所以Elasticsearch把对象层次展开到一个由属性名称和属性值组成的简单列表中。以下列文档为例:

curl -XPUT 'localhost:9200/my_index/my_type/1?pretty' -H 'Content-Type: application/json' -d '{
 "group" : "fans",
 "user" : [
   {
     "first" : "John",
     "last" :  "Smith"
   },
   {
     "first" : "Alice",
     "last" :  "White"
   }
 ]
}'

该请求会在内部转换为如下的文档形式:

{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}

如果需要索引对象数组,并维护数组中每个对象的依赖关系,应当使用内嵌数据类型而不是对象数据类型。内嵌对象在内部会把数组中的每个对象当作单独的隐藏文档来索引,即使用下述内嵌查询,可以单独查询每个内嵌对象:

curl -XPUT 'ES_HOST:ES_PORT/my_index?pretty' -H 'Content-Type: application/json' -d '{
 "mappings": {
   "my_type": {
     "properties": {
       "user": {
         "type": "nested"
       }
     }
   }
 }
}'

curl -XPUT 'ES_HOST:ES_PORT/my_index/my_type/1?pretty' -H 'Content-Type: application/json' -d '{
 "group" : "fans",
 "user" : [
   {
     "first" : "John",
     "last" :  "Smith"
   },
   {
     "first" : "Alice",
     "last" :  "White"
   }
 ]
}'


curl -XGET 'ES_HOST:ES_PORT/my_index/_search?pretty' -H 'Content-Type: application/json' -d '{
 "query": {
   "nested": {
     "path": "user",
     "query": {
       "bool": {
         "must": [
           { "match": { "user.first": "Alice" }},
           { "match": { "user.last":  "Smith" }}
         ]
       }
     }
   }
 }
}'

curl -XGET 'ES_HOST:ES_PORT/my_index/_search?pretty' -H 'Content-Type: application/json' -d '{
 "query": {
   "nested": {
     "path": "user",
     "query": {
       "bool": {
         "must": [
           { "match": { "user.first": "Alice" }},
           { "match": { "user.last":  "White" }}
         ]
       }
     },
     "inner_hits": {
       "highlight": {
         "fields": {
           "user.first": {}
         }
       }
     }
   }
 }
}'

当有一个主实体比如一篇博客文章,带有一些有一定关系但又不是非常重要的其他实体比如评论时,内嵌对象会非常有用。如果能根据评论内容来查询到博客文章,那就很不错,而且内嵌查询和过滤器一起提供了更快的join查询能力。

内嵌对象模型的缺点如下:

为了 增加 、修改 或 删除 一个内嵌对象文档,整个文档必须重建索引;这就导致内嵌文档越多开销就越大。

搜索请求返回整个文档,而不是只返回匹配的内嵌文档。虽然已经以后计划支持返回根文档的部分最配内嵌文档,但目前仍然不支持。

有时候可能需要把主文档和其关联实体分离,这种分离由父子关系来提供。

通过建立另一个文档的父类型mapping,可以在相同索引的文档之间建立父子关系:

curl -XPUT 'ES_HOST:ES_PORT/my_index?pretty' -H 'Content-Type: application/json' -d '{
 "mappings": {
   "my_parent": {},
   "my_child": {
     "_parent": {
       "type": "my_parent"
     }
   }
 }
}'

curl -XPUT 'ES_HOST:ES_PORT/my_index/my_parent/1?pretty' -H 'Content-Type: application/json' -d '{
 "text": "This is a parent document"
}'

curl -XPUT 'ES_HOST:ES_PORT/my_index/my_child/2?parent=1&pretty' -H 'Content-Type: application/json' -d '{
 "text": "This is a child document"
}'

curl -XPUT 'ES_HOST:ES_PORT/my_index/my_child/3?parent=1&refresh=true&pretty' -H 'Content-Type: application/json' -d '{
 "text": "This is another child document"
}'

curl -XGET 'ES_HOST:ES_PORT/my_index/my_parent/_search?pretty' -H 'Content-Type: application/json' -d '{
 "query": {
   "has_child": {
     "type": "my_child",
     "query": {
       "match": {
         "text": "child document"
       }
     }
   }
 }
}'

父子join对管理实体关系非常有用,尤其是在索引时间比检索时间很重要的情形下,但是它会带来较大的开销;父子查询比同等的内嵌查询要慢5到10倍。

2.全局序列号和延迟

父子关系使用了全局序列号来加速join操作。无论父子map是否使用了内存缓存或磁盘上的doc value,全局序列号仍然需要在索引发生任何改变时进行重建。

分片中的父代越多,全局序列号构建就越耗时。相对于需要父代和较少的子代, 父子关系最适合每个父代有很多子代的情形。

全局序列号默认是 延迟 构建:refresh后的第一个父子查询或聚合请求将会触发构建全局序列号。这会让用户感知到一个明显的潜在峰值。可以使用eager_global_ordinals 来把查询期构建全局序列号的成本转移到refresh期,通过如下方式mapping _parent属性:

curl -XPUT 'ES_HOST:ES_PORT/company -d ‘{
  "mappings": {
    "branch": {},
    "employee": {
      "_parent": {
        "type": "branch",
        "fielddata": {
          "loading": "eager_global_ordinals"
        }
      }
    }
  }
}’

这里,_parent属性的全局序列号将会在一个新的段搜索可见时被构建。

对于很多的父代,全局序列号要花费数秒钟来构建。此时,需要增加refresh_interval,以便refresh的频率更低,而全局序列号保持可用的时间更长。这将大幅减少每秒钟重建全局序列号的CPU消耗。

3.多代关系

对多代数据的Join(参考Grandparents and Grandchildren)能力听起来很吸引人,但需要思考其代价:

  • Join越多,性能越差。
  • 每一个父代都需要把自己的string _id属性保存在内存,这可能会消耗大量RAM。
  • 当考虑关系型方案及父子关系是否适合时,可参考下列关于父子关系的建议:
  • 保守使用父子关系,仅当子代比父代多很多时才考虑。
  • 避免在单个查询中使用多父子关系来join。
  • 避免对使用has_child过滤器,或score_mode为 none 的has_child查询来打分。
  • 父ID尽量简短,以便在doc value中更好地压缩,从而在瞬时加载时消耗更少的内存。

4.为文件系统缓存分配内存

对于运行中Elasticsearch,内存是需要密切监控的重要资源之一。Elasticsearch和Lucene通过JVM堆内存和文件系统缓存两种方式来消耗内存。由于Elasticsearch运行在Java虚拟机(JVM)中,所以JVM的GC周期和频率也需要重点监控。

JVM堆内存

对于Elasticsearch一个“刚好合适”的JVM堆大小是非常重要的——不能设置过大或过小,原因见后文。一般来说Elasticsearch的经验值是分配少于50%的可用RAM给JVM堆,且不要超过32GB。

为Elasticsearch分配过少的堆内存,那么就会留给Lucene更多内存,而Lucene重度依赖于文件系统缓存来快速处理请求。不管怎样也不能设置过小的堆内存,因为当应用由于频繁GC而面临短时中断时,可能会遭遇内存溢出错误或吞吐量下降。

Elasticsearch默认安装时设置的JVM堆大小为1GB,这在大多数情况下都偏小。可以通过环境变量来设置期望的对大小并重启Elasticsearch:

export ES_HEAP_SIZE=10g

设置JVM堆大小的另一种方式(相当于设置一样的最小值和最大值,以防止重新调整堆大小),是在每次启动Elasticsearch时通过命令行参数指定:

ES_HEAP_SIZE="10g" ./bin/elasticsearch

这两种示例方式都是设置了10GB的堆大小,为了验证是否设置成功,执行:

curl -XGET http://ES_HOST:9200/_cat/nodes?h=heap.max

返回的输出会显示已正确地更新了最大堆内存。

垃圾回收

Elasticsearch依靠GC过程来释放堆内存。由于GC本身也要消耗资源(为了释放资源!),所以应当留意GC频率和持续时间,以确认是否需要调整堆内存大小。设置过大的堆内存,换来的是更长的GC时间;这种过多的停顿非常危险,因为可能导致集群误认为该节点网络异常而失联。

因此,Elasticsearch重度依赖文件系统缓存来加速搜索。一般需要保证至少有一半的可用内存用于文件系统缓存,这样Elasticsearch才能保持索引数据的热点区域都在物理内存中。

使用更快的硬件

如果搜索受限于I/O,应当考虑为文件系统缓存分片更多内存(参考前文),或者购买更快的驱动。特别地,SSD公认地比机械磁盘性能好很多。尽可能使用本地存储,避免使用像 NFS 或 SMB 之类的远程或网络文件系统,也要注意像Amazon EBS这样的虚拟化存储。

Elasticsearch使用虚拟化存储工作是没有问题的,它因为快速和安装简单而受欢迎,但同样不幸的是,在基础上与专用的本地存储相比它天生就比较慢。如果在EBS上创建了一个索引库,请确认使用预分配的IOPS,否则很快就会被限流。

如果搜索受限于CPU,那么应当考虑购买更快的CPU。

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
目录
相关文章
|
12月前
|
缓存 监控 前端开发
顺企网 API 开发实战:搜索 / 详情接口从 0 到 1 落地(附 Elasticsearch 优化 + 错误速查)
企业API开发常陷参数、缓存、错误处理三大坑?本指南拆解顺企网双接口全流程,涵盖搜索优化、签名验证、限流应对,附可复用代码与错误速查表,助你2小时高效搞定开发,提升响应速度与稳定性。
|
存储 Linux iOS开发
Elasticsearch Enterprise 9.1.5 发布 - 分布式搜索和分析引擎
Elasticsearch Enterprise 9.1.5 (macOS, Linux, Windows) - 分布式搜索和分析引擎
754 0
|
JSON 监控 Java
Elasticsearch 分布式搜索与分析引擎技术详解与实践指南
本文档全面介绍 Elasticsearch 分布式搜索与分析引擎的核心概念、架构设计和实践应用。作为基于 Lucene 的分布式搜索引擎,Elasticsearch 提供了近实时的搜索能力、强大的数据分析功能和可扩展的分布式架构。本文将深入探讨其索引机制、查询 DSL、集群管理、性能优化以及与各种应用场景的集成,帮助开发者构建高性能的搜索和分析系统。
770 0
|
数据采集 人工智能 运维
从企业级 RAG 到 AI Assistant,阿里云Elasticsearch AI 搜索技术实践
本文介绍了阿里云 Elasticsearch 推出的创新型 AI 搜索方案
1168 3
从企业级 RAG 到 AI Assistant,阿里云Elasticsearch AI 搜索技术实践
|
存储 安全 Linux
Elasticsearch Enterprise 9.0 发布 - 分布式搜索和分析引擎
Elasticsearch Enterprise 9.0 (macOS, Linux, Windows) - 分布式搜索和分析引擎
618 0
|
存储 Linux iOS开发
Elasticsearch Enterprise 8.18 发布 - 分布式搜索和分析引擎
Elasticsearch Enterprise 8.18 (macOS, Linux, Windows) - 分布式搜索和分析引擎
554 0
|
人工智能 自然语言处理 搜索推荐
云端问道12期实操教学-构建基于Elasticsearch的企业级AI搜索应用
本文介绍了构建基于Elasticsearch的企业级AI搜索应用,涵盖了从传统关键词匹配到对话式问答的搜索形态演变。阿里云的AI搜索产品依托自研和开源(如Elasticsearch)引擎,提供高性能检索服务,支持千亿级数据毫秒响应。文章重点描述了AI搜索的三个核心关键点:精准结果、语义理解、高性能引擎,并展示了架构升级和典型应用场景,包括智能问答、电商导购、多模态图书及商品搜索等。通过实验部分,详细演示了如何使用阿里云ES搭建AI语义搜索Demo,涵盖模型创建、Pipeline配置、数据写入与检索测试等步骤,同时介绍了相关的计费模式。
600 3
|
数据采集 人工智能 运维
从企业级 RAG 到 AI Assistant,阿里云Elasticsearch AI 搜索技术实践
本文介绍了阿里云 Elasticsearch 推出的创新型 AI 搜索方案。
1346 5
|
人工智能 算法 API
构建基于 Elasticsearch 的企业级 AI 搜索应用
本文介绍了基于Elasticsearch构建企业级AI搜索应用的方案,重点讲解了RAG(检索增强生成)架构的实现。通过阿里云上的Elasticsearch AI搜索平台,简化了知识库文档抽取、文本切片等复杂流程,并结合稠密和稀疏向量的混合搜索技术,提升了召回和排序的准确性。此外,还探讨了Elastic的向量数据库优化措施及推理API的应用,展示了如何在云端高效实现精准的搜索与推理服务。未来将拓展至多模态数据和知识图谱,进一步提升RAG效果。
823 1
|
存储 缓存 监控
极致 ElasticSearch 调优,让你的ES 狂飙100倍!
尼恩分享了一篇关于提升Elasticsearch集群的整体性能和稳定性措施的文章。他从硬件、系统、JVM、集群、索引和查询等多个层面对ES的性能优化进行分析,帮助读者提升技术水平。

热门文章

最新文章