ES 索引创建最佳实践

4,807 阅读4分钟

本文 ES 版本基于 7.1.1

相对于之前的不同

移除 type

ES7 相对于之前的版本,最大的不同就是 es7 开始去掉了 type 这个概念(也就是之前用来类比关系型数据库中的表,这也是由于参考了关系型数据库,所以留下了 type 这个不合理的概念)

在 6.x 版本时,一个 index 下只能创建一个 type,这应该是一个过渡阶段。(6.x 版本之前是可以创建多个 type 的)

至于为什么要去掉 type 呢,但是同一索引下不同 type 下相同 filed 最终会被 lucene 映射到一起,所以在不同 type 中的相同字段就可能会出现冲突,从而导致效率降低。而去掉了 type 之后,一个 index 就是一个索引,它们都是独立存储的,所以也就不会出现冲突了,效率也就提升了。

移除 string 类型

ES 5.x 开始,已经移除了 string 类型,而是将字符串拆分为两种类型:text 和 keyword。前者用于全文模糊搜索(会做分词),后者用于精准匹配(不会做分词,适合关键字精准匹配)

这样就可以自己来控制是否要对字符串进行分词了,避免一些不必要的开销,最重要的是可以做一些精准匹配,在之前的 string 中,搜索一个关键字总是会得到一些不需要的结果(因为是全文匹配,所以只要匹配到关键字就会返回,而不会关心它是否是完整匹配的)。

最佳实践

避免使用动态创建

通过设置 dynamic 来动态创建新出现的字段,虽然在有时候这显得很方便(可以不提前定义字段,动态的将不定字段存入 es)但有时候这将会是糟糕的,因为有时候你错误的添加了一个字段,它也会被自动创建到索引字段中,这并不是我们所希望的,我们应该希望这时候报错,提示我们这里的存储有问题,我们才能及时的发现问题。

我们可以设置 dynamic 的值来控制动态映射。

  • true: 允许动态添加新的字段,这是默认值。
  • false: 忽略新的字段,不会自动为它创建索引。
  • strict: 如果遇到新的字段,会跑出异常。

合理使用 enabled

对于不需要索引的字段,可以设置为 enabled: false。例如存储请求日志时,你可能只会根据 uid, request_id 等来进行索引,而不会使用请求体或响应体去进行查询,(只需存储它们即可)这时候可以将它们设置为 enable: false,这样 es 就不会对它们进行索引,从而可以节省很大的存储开销。

合理使用 keyword 字段

有一些字段,你可能只需要对其精确匹配,不需要对其分词或者是范围查询,那么这个时候设置成 keyword 字段比设置成 text 字段或者是数值字段更能提高整体性能。而且还可以降低索引的使用空间,一般如果没有模糊匹配的场景,都建议将字符串字段设置为 keyword。

使用 index template

如果查询具有日期范围过滤子句,则按日期建立数据。 这适用于大多数日志记录和监控场景。我们可以按天、周或月组织索引,然后可以获得指定的日期范围内的索引列表,这样,Elasticsearch 只需要查询一个较小的数据集而不是整个数据集。另外,当数据过期时,删除旧的索引也很容易。

如果要每次自己来手动创建索引,这简直太麻烦了,es 的开发者们也考虑到了这点,所以为我们提供了索引模板。你可以创建一个索引模板,里面设置匹配规则,当写入的索引名匹配到索引模板时,将自动应用索引模板中的 settings 和 mappings。

索引生命周期管理(ilm)

参考官方文档 www.elastic.co/guide/en/el…

PUT _ilm/policy/log_save_policy
{
  "policy": {
    "phases": {
      "delete": {          // 定义删除阶段
        "min_age": "365d", // 删除阶段在 365 天后开始
        "actions": {       // 定义删除动作
          "delete": {}
        }
      }
    }
  }
}

索引模板创建

索引的 settings 和 mappings 具体参数设置: www.elastic.co/guide/en/el… www.elastic.co/guide/en/el…

PUT _template/req_log
{
  "order": 0,
  "index_patterns": ["req_log-*"],
  "settings": {
    "index": {
      "lifecycle": {
        "name": "log_save_policy" // 使用上面刚创建的生命周期策略。
      },
      "routing": {
        "allocation": {
          "enable": "all"         // 索引碎片分配策略
        }
      },
      "refresh_interval": "60s",  // 索引刷新频率(es 是近实时搜索的原因)
      "number_of_shards": "3",    // 分片数,一般等于机器实例数
      "number_of_replicas": "1",  // 副本数,一般设置为1
    }
  },
  "mappings": {                   // 索引字段映射
    "dynamic": "false",
    "properties": {
         
    }
  },
  "aliases": {                    // 索引别名
    "req_log": {}
  }
}

索引模板创建成功后,如果要指定按月创建索引,那么索引名称可以设置为 req_log-2020-06 ,它就会自动匹配到上面创建的模板,并应用模板配置。