关于Elasticsearch查询优化的问题纪实(index相关)未完结

背景:

  • 根据订单号查询该订单所对应的机器操作日志信息,客服反馈查询速度慢,最慢时候需要查询6、7秒才能返回数据。
  • ES配置为3台2C16G服务器支撑。总数据量为1亿7千万条。但用于此业务的数据条数不超过一千万条。
  • 该索引为按天新建索引,索引名称均为 order-log-2024-01-01、order-log-2024-01-02、order-log-2024-01-03 等,一天一个索引,单天的索引数据条数中位数约为30000条。
  • 索引字段模式均为ES自动映射的类型,即text + keyword + ignore_above 256类型。
  • 页面每五秒钟查询一次ES,每个人平均打开页面10个,目前平均10人使用此功能。
  • 其他ES设置均为ES默认设置,没有经过特别的调整修改。
  • 三分片一副本。
  • Elasticsearch版本 7.10.0 、Kibana版本 7.10.0。

问题描述:

  • 客服反馈查询订单的设备日志慢,2、3秒到7、8秒不等。
  • 查询效率慢。
  • 查询语句需要拼接索引名称,因为一个订单经常会跨天,如果跨三天,ES脚本中就要查询三个索引。

 要求:

  • 满足十个人,每个人开十个窗口使用此功能, 每个页面每5秒查询es一次。
  • 查询速度3秒内。
  • 应对日后可能会增长的数据量。

目录

一、测试人员首次进行ES查询压测,摸底当前ES查询性能  (已完成)

1、压测及结论

二、制定初步方案,运维人员根据方案进行实施操作  (已完成) 

   1、ES字段格式问题排查

   2、ES索引中数据排查

    3、ES索引创建逻辑排查        

    4、ES线程池排查 

   5、拟定方案与实施        

三、测试人员第二次进行ES查询压测,测试初步方案效果  (已完成) 

1、压测及结论

四、制定第二步方案,运维人员根据方案进行实施操作 (已完成) 

1、方案补充

2、ES索引模板语句编写

3、ES动态模板语句编写

4、拟定方案与实施 

 五、测试人员第三次进行ES查询压测,测试第二次方案效果  (未进行)

ES问题处理流程:

  1. 测试人员首次进行ES查询压测,摸底当前ES查询性能。(已完成)
  2. 制定初步方案,运维人员根据方案进行实施操作。(已完成)
  3. 测试人员第二次进行ES查询压测,测试初步方案效果。(已完成)
  4. 制定第二步方案,运维人员根据方案进行实施操作。(已完成)
  5. 测试人员第三次进行ES查询压测,测试第二次方案效果。
  6. 根据三轮压测确定方案生产可行性评估。
  7. 产品确定各个业务字段的业务意义,确定最终字段格式交付运维。
  8. 制定生产数据处理(清洗)方案,准备实施。
  9. 生产ES数据改造实施。
  10. 测试人员对生产环境进行压测,测试生产环境改造后效果。
  11. 评估改造结果,复盘过程,记录改造过程文档,形成有效的方法论。

压测查询方式:

  • 模拟业务实际查询参数进行ES查询语句的编写。
  • 根据订单id和设备id进行精确查询。
  • 拼接索引名称。(因为订单跨天,所以需要把订单涉及的几天都拼接到需要查询到的es的索引名中) 
  • es语句约为设备id做must、订单id做should、timestamp为指定区间段进行查询。
  • 索引查询为多个索引,例[order-log-2024-01-01, order-log-2024-01-02, order-log-2024-01-03] ,数量不封顶。

一、测试人员首次进行ES查询压测,摸底当前ES查询性能  (已完成)

1、压测及结论
  • 当前问题已经明确,需要测试人员进行压测来摸出ES目前的真实性能,根据结果来制定优化方案。
  • 测试人员压测结果如下:
  • 根据压测结果来看,在并发数接近50的时候,查询时间会接近5秒,而且有继续增加的倾向。

二、制定初步方案,运维人员根据方案进行实施操作  (已完成) 

      思路:从ES字段格式、索引创建逻辑、服务器查询负载、ES线程池信息入手。

   1、ES字段格式问题排查
  • 询问后得知,ES在使用初期并没有使用指定的字段映射,在新索引插入的时候,每个字段都是使用的ES的默认动态映射,由于目前ES写入的数据均为String类型,所以根据ES的自动映射,所有业务字段类型都为 text + keyword 模式。 如下图所示:

  • 所有String类型的字段格式都为 text + keyword 类型,但实际上我们在查询时只会针对三个字段进行精确查询和一个日期字段的区间查询。
  • 初步跟产品进行沟通,确认目前查询的需求只有部分字段的精确查询后,确定ES需要新增索引模板,索引模板用来约束索引中的字段格式,手动映射每个字段,而不是让ES自行决定字段的格式。
  • 文本类型(text)关键字类型(keyword)区别
    1. text类型(文本类型)会使用默认分词器分词,也就是存入的数据会先进行分词,然后将分完词的词组存入索引,当然你也可以为他指定特定的分词器。
    2. keyword类型(关键字类型),那么默认就不会对其进行分词,原样存储。当一个字段需要按照精确值进行过滤、排序、聚合等操作时, 就应该使用keyword类型。
  • 如果没有分词需求而使用了text类型,ES会做很多对业务无意义的操作,反而给我们的查询徒增负担,而且也会影响ES的写入效率。
  • 而且对于磁盘占用量也会显著降低。(因为很多字段不需要分词,ES也不需要进行倒排索引记录)

   2、ES索引中数据排查
  • 查看本业务所对应的ES索引数据,排查是否有无用数据。
  • 发现在该业务中,ES中记录了请求logstash时请求头的信息,而且此header中的所有字段也均为ES自动映射的字段类型,即text 和 keyword。如下图所示。

  • 图中可见,header中,不仅字段众多,字段数量甚至都超过了业务字段的数量,而且其中还有一个字段为大文本,这种情况下,ES为其设置的类型依然为text + keyword。这注定ES为这个永远用不到的字段耗费了太多无意义的用功和储存。
  • 鉴于header中的数据都为以外写入,而且不具备实用意义。所以建议在数据转移/清洗时去除。
  • 各方查询此header数据是哪一个环境插入的,如无意义则停止写入header信息。

    3、ES索引创建逻辑排查        
  • 目前索引的创建逻辑为每天一个索引,用索引末尾的日期来表明该索引是哪一天的。例如 order-log-2024-01-01、order-log-2024-03-15 等。
  • 根据Kibana中的索引信息显示,每天的数据条数都不大,单天最大为3W左右,如下图所示:
  • 如果按照每天都是3W条来计算,单月最大数据量为93W,所以对于ES单索引而言,完全不具备任何问题。ES中的数据没有大文本,业务字段目前不超过20个。
  • 所以目前倾向将ES索引创建修改为按月或者按季度甚至是按年为单位,一来减少多索引导致的分片数过多、JVM优化等问题,二来将客户端查询时拼接的索引名拼接方式给去除掉。

    4、ES线程池排查 
  • 查询服务器查询负载、ES线程池信息
  • 目前根据运维反馈,ES服务器的负载并不大,服务器性能仍有压榨的空间。
  • 查询ES线程池发现,目前ES中threadPool中的search为4,如下图所示:

  • 建议在测试人员进行压测时,运维监控ES服务器负载状态,根据情况适当调大查询线程池数量。

   5、拟定方案与实施        

  • 目前根据信息,得出初步实施计划,计划如下:
    • 选择生产环境近15天数据(15个索引),转移至测试专用ES实例中。
    • 转移时去除原索引数据中的header部分数据。
    • 增加索引模板,规范各个业务字段的格式。
    • 将15天的索引合并到一个索引中。
    • 适当调节线程池查询数量。

  • 运维实际实施结果:

    • 选择生产环境近15天数据(15个索引),转移至测试专用ES实例中。√
    • 转移时去除原索引数据中的header部分数据。√
    • 增加索引模板,规范各个业务字段的格式。
    • 将15天的索引合并到一个索引中。
    • 适当调节线程池查询数量。
    • ES服务器中CPU模式由商业版变更为内核增强版。索引创建场景由通用场景切换到搜索场景。√

三、测试人员第二次进行ES查询压测,测试初步方案效果  (已完成) 

1、压测及结论
  • 上一阶段具体实施结果与计划存在些许差异,测试人员在当前情况下任然决定进行一次压力测试来验证当前ES的改动是否改善了查询性能。
  • 猜测:由于只迁移了15天(15个)索引的数据,所以数据量的大幅降低或许会提高查询性能。而且在迁移这15天的索引数据时,去除了原索引中又长又无用的header字段的数据,所以会很大程度的减轻ES的负担(header中的数据比业务字段数据都大),综上所述,压测结果应该会好于第一次摸底压测。
  • 压测方式,依然使用订单ID和设备ID精准查询,并使用日期字段的区间限制进行筛选。
  • 但之前所说的需要拼接对应的ES索引名称依然没有改变。(比如要查询2024-01-01和2024-01-02的ES数据,就依然要显性的指定查询索引的索引为 [order-log-2024-01-01, order-log-2024-01-02])。
  • 实际上只是查15天的数据,而且把又臭又长的header数据干掉了而已。
  • 压测结果如下:

  • 压测结果:
    • 满足初始查询速度要求。但数据量过少,无法推测大数据量场景结果。
    • TPS与平均响应时间较第一次压测,有大幅度提升。但不排除是数据量只有15天的原因所致。
    • 索引场景模式从通用场景切换到搜索场景、CPU由商业版切换为内核增强版后,性能较有所提升,但具体提升多少不可知。
    • 在多个线程并发的情况下,目前出现少量的报错现象,目前未查明原因。
    • 切换搜索场景后,写入性能是否会受影响暂不可知。

四、制定第二步方案,运维人员根据方案进行实施操作 (已完成) 

1、方案补充
  • 由于索引数量仍然是15天(15个),且字段格式仍没有矫正,所以经协商后,要求运维继续推进原有方案。
    • 增加索引模板,规范各个业务字段的格式。
    • 将15天的索引合并到一个索引中。
    • 适当调节线程池查询数量。
  • 在上一次没有实施完的方案继续推进的基础上,增加一个需求点,增加ES动态模板的设置,防止如果有索引模板中不存在的字段写入后,字段仍然是ES自动映射的 text + keyword 模式。
    • 设置ES动态模板 DynamicTemplate。
    • 目前先简单设置,将String类型的数据自动映射为keyword类型。
2、ES索引模板语句编写
  • 编写创建ES索引模板语句(语句仅为示例,详细设置请百度关键词 ES索引模板),此处不进行模板语句解释。
  • 实际情况中,编写完后需要交给运维进行检查,并进一步补充其他的设置项,需要交由运维对其语句进行补充、打磨、审阅后执行。
  • PS:ES 7.x 需要把语句中的 "_doc": 这一层去掉,ES 7不支持这个关键字了。
PUT /_template/xxx-xxx-log-xxx-test-template
{
  "index_patterns": ["xxx-xxx-xxx-info-*"],
  "order": 10,
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "10s"
  },
  "aliases": {
    "aliases_names": {}
  },
   "mappings": {
    "_doc": {
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "@version": {
          "type": "keyword",
          "index": "false",
          "norms": "false"
        },
        "buildType": {
          "type": "keyword",
          "index": "false",
          "norms": "false"
        },
        "createTime": {
          "type": "keyword",
          "index": "true",
          "norms": "true"
        },
        "creator": {
          "type": "keyword",
          "index": "true",
          "norms": "true"
        },
        "deviceId": {
          "type": "keyword",
          "index": "true",
          "norms": "true"
        },
        "handleType": {
          "type": "keyword",
          "index": "true",
          "norms": "false"
        },
        "sn": {
           "type": "keyword",
          "index": "true",
          "norms": "false"
        }
      }
    }
  }
}

3、ES动态模板语句编写
  • 编写动态模板语句,规范日后进入的ES字段。
  • 大致意思为在索引模板以外的字段、类型为string的数据写入ES时,默认映射为keyword模式,index不索引。
  • 具体其他书写方式以及使用方式请自行搜索。
  • 编写完后需要交给运维进行检查,并进一步补充其他的设置项,需要交由运维对其语句进行补充、打磨、审阅后执行。
PUT my_index_xxxx
{
    "mappings": {
        "dynamic_templates": [{
                "strings_as_keywords": {
                    "match_mapping_type": "string",
                    "mapping": {
                        "type": "keyword",
                        "index": "false",
                        "norms": "false"
                    }
                }
            }
        ]
    }
}
4、拟定方案与实施 

  • 根据目前情况,计划如下:
    • 增加索引模板,规范各个业务字段的格式。
    • 将15天的索引合并到一个索引中。
    • 适当调节线程池查询数量。
    • 设置ES动态模板 DynamicTemplate。

  • 运维实际实施结果

    • 增加索引模板,规范各个业务字段的格式。 √
    • 将15天的索引合并到一个索引中。 √
    • 适当调节线程池查询数量。
    • 设置ES动态模板 DynamicTemplate。 尚未得到通知

 五、测试人员第三次进行ES查询压测,测试第二次方案效果  (未进行)

 

 未完.....

  • 27
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值