乐趣区

关于后端:如何优化因为高亮造成的大文本大字段检索缓慢问题

首先还是说一下背景,工作中用到了 elasticsearch 的检索以及高亮展现,然而索引中的 content 字段是读取的大文本内容,所以结果就是索引的单个字段很大,造成独自检索申请的时候速度还能够,然而退出高亮之后检索申请的耗时就十分的慢了。所以本文从 更换高亮器类型 的角度来解决因为高亮造成的检索申请迟缓的问题。

ES 的对消策略

在文章开始前先简略介绍一个 elasticsearch 的策略,为了在检索的字段中创立出一个有意义的高亮片段,高亮器会应用原始文本的开始和完结字符串的偏移量,偏移量的获取能够从一下形式取得

  • postings list:如果在 mappingindex_options设置为 offsetsunified 高亮器应用此信息高亮显示文档而不必再次剖析文本。
  • term vectors:如果咱们在 mapping 中设置 term_vectorwith_positions_offsets,则 unified 高亮器会主动应用 term_vector 来高亮显示,对于大于 1M 的大字段,应用 term_vector 速度会很快,fvh高亮器就是应用的term_vector
  • plain highlighting:当 unified 没有其余的抉择的时候会应用 plain 模式,它会创立了一个渺小的内存索引,并通过 Lucene 的查问执行打算器从新运行原始查问条件。plain高亮器默认应用的就是此模式

大文本的纯高亮展现可能须要大量的工夫和内存,为了避免这种状况,es 默认将大文本的字符数量限度为 1000000,能够应用index.highlight.max_analyzed_offset 批改此默认设置

一、FVH 高亮器简介

FVH(Fast Vector Highlighter)是 Elasticsearch 高亮器中的一种算法,应用的是Lucene Fast Vector highlighter,它可能疾速而精确地在文本中找到匹配的关键词,并将其标记为高亮。相比于其余高亮器算法,FVH 在性能上有着显著的劣势,特地实用于大规模数据集和高并发的场景。

二、FVH 高亮器的应用办法

装置

首先,确保曾经正确装置了 Elasticsearch

version: '3.8'
services:
  cerebro:
    image: lmenezes/cerebro:0.8.3
    container_name: cerebro
    ports:
     - "9000:9000"
    command:
     - -Dhosts.0.host=http://eshot:9200
    networks:
     - elastic
  kibana:
    image: docker.elastic.co/kibana/kibana:8.1.3
    container_name: kibana
    environment:
      - I18N_LOCALE=zh-CN
      - XPACK_GRAPH_ENABLED=true
      - TIMELION_ENABLED=true
      - XPACK_MONITORING_COLLECTION_ENABLED="true"
      - ELASTICSEARCH_HOSTS=http://eshot:9200
      - server.publicBaseUrl=http://192.168.160.234:5601
    ports:
      - "5601:5601"
    networks:
      - elastic
  eshot:
    image: elasticsearch:8.1.3
    container_name: eshot
    environment:
      - node.name=eshot
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=eshot,eswarm,escold
      - cluster.initial_master_nodes=eshot,eswarm,escold
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
      - node.attr.node_type=hot
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - D:\zuiyuftp\docker\es8.1\eshot\data:/usr/share/elasticsearch/data
      - D:\zuiyuftp\docker\es8.1\eshot\logs:/usr/share/elasticsearch/logs
      - D:\zuiyuftp\docker\es8.1\eshot\plugins:/usr/share/elasticsearch/plugins
    ports:
      - 9200:9200
    networks:
      - elastic
  eswarm:
    image: elasticsearch:8.1.3
    container_name: eswarm
    environment:
      - node.name=eswarm
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=eshot,eswarm,escold
      - cluster.initial_master_nodes=eshot,eswarm,escold
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
      - node.attr.node_type=warm
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - D:\zuiyuftp\docker\es8.1\eswarm\data:/usr/share/elasticsearch/data
      - D:\zuiyuftp\docker\es8.1\eswarm\logs:/usr/share/elasticsearch/logs
      - D:\zuiyuftp\docker\es8.1\eshot\plugins:/usr/share/elasticsearch/plugins
    networks:
      - elastic
  escold:
    image: elasticsearch:8.1.3
    container_name: escold
    environment:
      - node.name=escold
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=eshot,eswarm,escold
      - cluster.initial_master_nodes=eshot,eswarm,escold
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
      - node.attr.node_type=cold
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - D:\zuiyuftp\docker\es8.1\escold\data:/usr/share/elasticsearch/data
      - D:\zuiyuftp\docker\es8.1\escold\logs:/usr/share/elasticsearch/logs
      - D:\zuiyuftp\docker\es8.1\eshot\plugins:/usr/share/elasticsearch/plugins
    networks:
      - elastic

# volumes:
#   eshotdata:
#     driver: local
#   eswarmdata:
#     driver: local
#   escolddata:
#     driver: local

networks:
  elastic:
    driver: bridge

创立索引

在应用 FVH 高亮器之前,须要先创立一个索引,并将须要高亮的字段进行映射。例如,咱们要在 content 字段中进行高亮,能够应用以下代码:

PUT /example_target
{
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "term_vector": "with_positions_offsets"
      },
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "term_vector": "with_positions_offsets"
      }
    }
  }
}

增加测试数据

POST example_target/_doc
{
  "content":"中华人民共和国是否思考是否就爱上速度放慢合成 ask 计算机卡死撒中华上的飞机拉丝机是的中央记录 卡就是开发建设看积分卡说了句 ask 就疯狂萨拉丁就发士大 sdf 看得见啊李开复 圣诞节卡了 夫哈数据库中华啊,中华,人民爱上中华",
  "title":"中华人名共和国"
}

查问并高亮

应用 FVH 高亮器进行查问和高亮的过程如下所示:

GET example_target/_search
{
  "query": {
    "match": {"content": "中华 爱上"}
  },
  "highlight": {
    "pre_tags": "<em>",
    "post_tags": "</em>", 
    "require_field_match": "false", 
    "fields": {
      "content": {
         "type": "fvh",
        "fragment_size": 18,
        "number_of_fragments": 3
      }
    }
  }
}

以上代码中,咱们通过 match 查问找到了蕴含关键词的文档,而后在 highlight 内容中指定了须要高亮的字段,这里是 content。执行述查问后,Elasticsearch 将返回匹配的后果,并在content 字段中增加了高亮标记。

数据量少的时候比照不是特地显著,所以在测试时,能够在索引中增加大量的测试数据进行测试,自己在测试过程中 es 的索引大小在 500M 左右,单个字段纯文本大小也有 1-2M。此时这种数据规模下应用一般的高亮器在检索申请时就曾经十分迟缓了,依据返回的数据量多少来决定,在取10 条数据时曾经能达到 6 秒了,然而在应用 fvh 高亮器之后工夫曾经进入毫秒级

三、FVH 高亮器的参数配置

先看一下返回的数据后果在对照上面参数学习

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.41193593,
    "hits" : [
      {
        "_index" : "example_target",
        "_id" : "f1rkC4oBCDmhQc2yo6PQ",
        "_score" : 0.41193593,
        "_source" : {"content" : "中华人民共和国是否思考是否就爱上速度放慢合成 ask 计算机卡死撒中华上的飞机拉丝机是的中央记录 卡就是开发建设看积分卡说了句 ask 就疯狂萨拉丁就发士大 sdf 看得见啊李开复 圣诞节卡了 夫哈数据库中华啊,中华,人民爱上中华"},
        "highlight" : {
          "content" : [
            "<em> 中华 </em> 人民共和国是否思考是否就 <em> 爱上 </em> 速度",
            "sk 计算机卡死撒 <em> 中华 </em> 上的飞机拉丝机是的中央记录",
            "夫哈数据库 <em> 中华 </em> 啊,<em> 中华 </em>,人民 <em> 爱上 </em> 中华"
          ]
        }
      },
      {
        "_index" : "example_target",
        "_id" : "G3Fi44kB4IVEhjafHXOf",
        "_score" : 0.33311102,
        "_source" : {"content" : "中华人民共和国是否思考是否就爱上速度放慢合成 ask 计算机卡死撒中华上的飞机拉丝机是的中央记录卡就是开发建设看积分卡说了句 ask 就疯狂萨拉丁就发士大夫哈数据库"},
        "highlight" : {
          "content" : [
            "<em> 中华 </em> 人民共和国是否思考是否就 <em> 爱上 </em> 速度",
            "sk 计算机卡死撒 <em> 中华 </em> 上的飞机拉丝机是"
          ]
        }
      },
      {
        "_index" : "example_target",
        "_id" : "HHFt44kB4IVEhjafE3Ov",
        "_score" : 0.31932122,
        "_source" : {"content" : "中华人民共和国是否思考是否就爱上速度放慢合成 ask 计算机卡死撒中华上的飞机拉丝机是的中央记录 卡就是开发建设看积分卡说了句 ask 就疯狂萨拉丁就发士大 sdf 看得见啊李开复 圣诞节卡了 夫哈数据库"},
        "highlight" : {
          "content" : [
            "<em> 中华 </em> 人民共和国是否思考是否就 <em> 爱上 </em> 速度",
            "sk 计算机卡死撒 <em> 中华 </em> 上的飞机拉丝机是的中央记录"
          ]
        }
      }
    ]
  }
}

通过下面的查问申请中高亮参数的指定能够发现,高亮器还是反对其余的参数的,那么咱们上面将对几个罕用的参数进行阐明

  • fragment_size:指定每个高亮片段的长度,默认为 100 个字符。
  • number_of_fragments:指定返回的高亮片段数量,默认为 5 个。
  • pre_tagspost_tags:别离指定高亮标记的前缀和后缀,默认为<em></em>
  • require_field_match:指定是否要求所有字段都匹配关键词才进行高亮,默认为 true。能够开启敞开此参数对下面的title 字段进行校验
  • type:指定 fvh 高亮器,除了 fvh 之外还有unifiedplain

    • unified 是默认的高亮器,能够将文本合成为句子,并应用 BM25 算法对单个句子进行评分,还反对准确的短语高亮显示,反对(fuzzyprefixregex)高亮。
    • plain 一般的高亮器,实用与简略的查问或者单个字段的匹配。为了精确的反馈查问逻辑,它会在内存中创立一个很小的索引,来对原始的查问语句进行执行,来拜访以后更低级别的匹配信息。

在应用 FVH 高亮器时,依据理论需要,能够灵便地调整这些参数,以获得最佳的高亮成果。

总结

通过本文的介绍,咱们理解了 Elasticsearch 高亮器中的 FVH 算法,并学会了如何应用它为搜寻后果削减亮点。FVH高亮器在性能和性能上都有着显著的劣势,对于大规模数据集和高并发的场景尤为实用。心愿读者通过本文的指引,可能更好地利用 FVH 高亮器来晋升搜寻后果的可读性和用户体验。

参考链接

https://www.elastic.co/guide/en/elasticsearch/reference/8.1/h…

如果感觉本文对你有所帮忙欢送点赞评论转发珍藏。如果你想理解更多对于 ES 的骚操作,更多实战经验,欢送关注。

原文链接
https://mp.weixin.qq.com/s?__biz=MzIwNzYzODIxMw==&mid=2247486065&idx=1&sn=28ee03fd0e297eb0c5d62405446d4551&chksm=970e11dba07998cd53a3a16e39e396172c3e3b46f96bab0e097eeab08fefb93c63b0d48fe380#rd

本文由 mdnice 多平台公布

退出移动版