在工作中 ElasticSearch 的一些使用规范总结

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 自己在工作中总结的关于 ElasticSearch 的一些使用规范,如有不当的地方,欢迎指正。

前言

大家好,我是路由器没有路

今天跟大家聊下自己在工作中总结的关于使用 ElasticSearch 的一些规范,如有不当的地方,欢迎指正。

Elasticsearch 是一个基于 Lucene 的搜索引擎,支持分布式搜索、多租户、实时搜索和分析等能力,具有高效、稳定、可扩展的优势,被广泛应用于企业级搜索和数据分析场景。

关于 ElasticSearch 的介绍,这里不再赘述了,有兴趣的同学可以看下我前面写的一篇文章:Elasticsearch 的简单介绍和如何使用

基础配置规划

分片(shard)容量

  • 非日志型(搜索型、线上业务型)的 shard 容量在 20~40GB(建议在 20G)
  • 日志型的 shard 容量在 35~100GB(建议 35G)
  • 单个 shard 的文档个数不能超过 20 亿左右(Integer.MAX_VALUE - 128)

注:一个 shard 就是一个 lucene 分片,ES 底层基于 lucene 实现。

索引(index)数量

大索引需要拆分:提高性能,降低风险,将风险分散化。

反例:例如一个 10 多 T 的索引,按 date 查询、name 查询

正例:indexname 拆成多个 index_name\${date}

正例:indexname 按 hash 拆分 index_name{1,2,3,...100..}

节点、分片、索引

一个节点管理的 shard 数不要超过 200 个

索引 mapping 的设计原则

大原则:不使用默认配置和动态 mapping、数据用途(类型、分词、存储、排序)弄清,下面是一个标准 mapping

{
   
  "aliases": {
   
    "my_index_name": {
   }
  },
  "settings": {
   
    "index": {
   
      "refresh_interval": "1s",
      "number_of_shards": "12",
      "number_of_replicas": "1",
      "search.slowlog.threshold.query.warn": "5s",
      "search.slowlog.threshold.query.info": "1s",
      "search.slowlog.threshold.fetch.warn": "1s",
      "search.slowlog.threshold.fetch.info": "800ms",
      "indexing.slowlog.threshold.index.warn": "12s",
      "indexing.slowlog.threshold.index.info": "2s"
    }
  },
  "mappings": {
   
    "_default_": {
   
      "_all": {
   
        "enables": false
      }
    },
    "my_type_name": {
   
      "properties": {
   
        "xxx_id": {
   
          "type": "keyword"
        },
        "timestamp": {
   
          "type": "long"
        },
        "xxx_status": {
   
          "type": "integer"
        },
        "xxx_content": {
   
          "type": "ztext"
        }
      }
    }
  }
}

refresh 频率(refresh_interval)

ES 的定位是准实时搜索引擎,该值默认是 1s,表示写入后 1 秒后可被搜索到,所以这里的值取决于业务对实时性的要求。

注意这里并不是越小越好,刷新频率高也意味着对 ES 的开销也大,通常业务类型在 1-5s,日志型在 30s-120s,如果集中导入数据可将其设置为-1,ES 会自动完成数据刷新(注意完成后更改回来,否则后续会出现搜索不到数据)。

别名(aliases)

记住:在某些场景下可使用别名,但不要过度依赖别名功能。

正例

索引名:index_name_v1

别名:index_name

未来重建 index_name_v2 索引,对于业务来说只需要换别名。

type 个数

1 个就够了,从 ES6 开始只支持一个 type,这个 type 比较鸡肋,后面的版本可能会去掉。

如果一定用:针对已经使用多个 type 的场景,一定要保证不同 type 下字段尽量保持一致,否则会加大数据稀疏性,存储与查询性能受影响

慢日志(slowlog)

一定要配置,默认不记录慢查询,kcc 提供了 grafana、kibana 查询功能。

副本(number_of_replicas)

1 个就够用,副本多写入压力不可忽视。极端情况下:譬如批量导入数据,可以将其调整为 0。

字段设计

  • textkeyword 的用途必须分清:分词和关键词(确定字段是否需要分词)

  • 确定字段是否需要独立存储

  • 字段类型不支持修改,必须谨慎

  • 对不需要进行聚合/排序的字段禁用 doc_values

  • 不要在 text 做模糊搜索

text 类型:适用于分词用于搜索,适用于 email 、内容、描述等需要分词的全文检索,不适用聚合。

keyword 类型:无需分词,整段完整精确匹配,适用于:email 、地址、状态码、分类 tags。

设置合理的 routing key(默认是 id)

id 不均衡:集群容量和访问不均衡,对于分布式存储是致命的。

关闭 _all

ES6.0 已经去掉,对容量(索引过大)和性能(性能下降)都有影响。

避免大宽表:

ES 默认最大 1000,但建议不要超过 100

text 类型的字段不要使用聚合查询

text 类型 fileddata 会加大对内存的占用,如果有需求使用,建议使用 keyword

聚合查询避免使用过多嵌套,

聚合查询的中间结果和最终结果都会在内存中进行,嵌套过多,会导致内存耗尽。

以下是聚合就嵌套了 3 层,结果都会保存在内存中,

如果唯一值较多,就会导致内存耗尽:

{
   
  "aggs": {
   
    "country": {
   
      "terms": {
   
        "filed": "country",
        "size": 10
      },
      "aggs": {
   
        "city": {
   
          "terms": {
   
            "filed": "city",
            "size": 20
          },
          "aggs": {
   
            "salary": {
   
              "terms": {
   
                "filed": "salary",
                "size": 20
              }
            }
          }
        }
      }
    }
  }
}

谨慎操作

  1. 原则:不要忽略设计,快就是慢,坏的索引设计后患无穷.
  2. 拒绝大聚合 :ES 计算都在 JVM 内存中完成。
  3. 拒绝模糊查询:es 一大杀手

    wildcard 搜索

    {
         
      "query": {
         
        "wildcard": {
         
          "title.keyword": "*张三*"
        }
      }
    }
    
  4. 拒绝深度分页
    ES 获取数据时,每次默认最多获取 10000 条,获取更多需要分页,但存在深度分页问题,一定不要使用 from/Size 方式,建议使用 scroll 或者 searchAfter 方式。

    scroll 会把上一次查询结果缓存一定时间(通过配置 scroll=1m 实现),所以在使用 scroll 时一定要保证 search 结果集不要太大。

  5. 基数查询
    尽量不要用基数查询去查询去重后的数据量大小(kibana 中界面上显示是 Unique Count,Distinct Count 等)

    即少用以下查询:

    "aggregations": {
         
        "cardinality": {
         
            "field": "userId"
        }
    }
    
  6. 禁止查询 indexName-*

  7. 避免使用 scriptupdate_by_querydelete_by_query,对线上性能影响较大。

需注意的问题

  1. 一个索引的 shard 数一旦确定不能改变
  2. ES 不支持事务 ACID 特性。
  3. reindex
    reindex 可以实现索引的 shard 变更,但代价非常大:速度慢、对性能有影响,所以好的设计和规划更重要

总结

以上是自己在工作中总结的关于 ElasticSearch 的使用规范,如对你有帮助,可以给个赞。

另外,Elasticsearch 的使用需要结合实际业务场景,通过优化和管理来提高其性能和稳定性,我们需要根据特定的业务场景和使用需求来选择合适的方案。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
6月前
|
存储 人工智能 API
Elasticsearch实战:常见错误及详细解决方案
Elasticsearch实战:常见错误及详细解决方案
|
9月前
|
Java 关系型数据库 MySQL
后端开发4.Elasticsearch的搭建
后端开发4.Elasticsearch的搭建
36 0
|
11月前
|
自然语言处理 Java API
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(一)
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践
97 0
|
11月前
|
缓存
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(三)
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(三)
64 0
|
11月前
|
SQL 关系型数据库 MySQL
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(五)
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(五)
60 0
|
11月前
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(四)
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(四)
51 0
|
11月前
|
自然语言处理
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(二)
【ElasticSearch从入门到放弃系列 十一】Elasticsearch常用查询方式讨论及实践(二)
65 0
|
API 索引
Elasticsearch Elasticsearch入门指导
Elasticsearch Elasticsearch入门指导
81 0
|
缓存 Dubbo NoSQL
【ElasticSearch实战】——ES在项目中应用方案设计
【ElasticSearch实战】——ES在项目中应用方案设计
569 0
【ElasticSearch实战】——ES在项目中应用方案设计
|
存储 缓存 自然语言处理
浅述Elasticsearch开发规范指南(持续更新)(上)
Elasticsearch 是一款流行的分布式开源搜索和数据分析引擎,具备高性能、易扩展、容错性强等特点。它强化了 Apache Lucene 的搜索能力,把掌控海量数据索引和查询的方式提升到一个新的层次。 本文将根据ElasticSearch的特点和日常开发中的经验,整理了在日常使用ElasticSearch进行开发的一些最佳实践。