ElasticSearch | 数据建模 | 最佳实践

建议一 | 如何处理关联关系

  • Object - 优先考虑 Denomalization;
  • Nested Object - 当数据包含多数值对象(多个演员),同时有查询需求;
  • Child / Parent - 关联文档更新分厂频繁时;
Kibana
  • Kibana 目前暂不支持 Nested Object 和 Parent / Child 类型,在未来有可能支持;
  • 如果需要使用 Kibana 进行数据分析,在数据建模时,仍需要对 Nested Object 和 Parent / Child 类型做出取舍;

建议二 | 避免过多字段

  • 一个文档中,最好避免大量的字段;
    • 过多的字段数不容易维护;
    • Mapping 信息保存在 Cluster State 中,数据量过大,对集群性能会有影响(Cluster State 信息需要和所有节点同步);
    • 删除或修改数据需要 Reindex;
  • 默认最大字段数是 1000,可以设置 index.mapping.total_field.limit 限定最大字段数;
什么情况会导致成百上千的字段?
  • 索引的 Mapping 的 dynamic 设置成了 true;随着新文档的写入,新文档有新字段,Mapping 中记录的索引的字段数就越来越多,引发 Mapping 文件膨胀的问题;
  • 解决方案:Nested Object & Key Value;
Dynamic 的取值
  • true - 未知字段会被自动加入
  • false - 新字段不会被索引,但是会保存在 _source 中;
  • strict - 新增字段不会被索引,文档写入失败;
使用 Nested Object & Key Value 解决字段过多的问题 | 示例
  • cookies 字段的 type 设置成 nested
  • 然后可以在 cookie 字段中设置不同类型的数据,它们以 key - value 的形式存储不同的字段的字段值;
PUT cookie_service
{
  "mappings": {
    "properties": {
      "cookies": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "keyword"
          },
          "dateValue": {
            "type": "date"
          },
          "keywordValue": {
            "type": "keyword"
          },
          "IntValue": {
            "type": "integer"
          }
        }
      },
      "url": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}
  • 使用 Nested Object & Key Value 的形式存储多字段,查询要这么查;
POST cookie_service/_search
{
  "query": {
    "nested": {
      "path": "cookies",
      "query": {
        "bool": {
          "filter": [
            {
              "term": {
                "cookies.name": "age"
              }
            },
            {
              "range":{
                "cookies.intValue":{
                  "gte":30
                }
              }
            }
          ]
        }
      }
    }
  }
}
使用 Nested Object & Key Value 解决字段过多的问题 | 弊端
  • 导致查询语句复杂度增加;
  • Nested 对象,不利于在 Kibana 中实现可视化分析;

建模建议三 | 避免正则查询

  • 正则,通配符查询,前缀查询都属于 Term 查询,但是性能不够好;
  • 特别是将通配符放在开头,会导致性能的灾难;
案例 | 查寻所有版本是 7.1 开头的 ElasticSearch 信息
  • 比如文档中有字段形如:"version":"7.1.1";
  • 可以把字符串转换成对象;
# 在Mapping中加入元信息,便于管理
PUT softwares/
{
  "mappings": {
    "_meta": {
      "software_version_mapping": "1.0"
    }
  }
}

GET softwares/_mapping
PUT softwares/_doc/1
{
  "software_version":"7.1.0"
}

DELETE softwares
# 优化,使用inner object
PUT softwares/
{
  "mappings": {
    "_meta": {
      "software_version_mapping": "1.1"
    },
    "properties": {
      "version": {
        "properties": {
          "display_name": {
            "type": "keyword"
          },
          "hot_fix": {
            "type": "byte"
          },
          "marjor": {
            "type": "byte"
          },
          "minor": {
            "type": "byte"
          }
        }
      }
    }
  }
}

建议四 | 避免空值引起的聚合不准

空值引起的聚合不准 | 案例
  • 聚合出来的平均值是 5,不对;
PUT ratings/_doc/1
{
 "rating":5
}
PUT ratings/_doc/2
{
 "rating":null
}

POST ratings/_search
POST ratings/_search
{
  "size": 0,
  "aggs": {
    "avg": {
      "avg": {
        "field": "rating"
      }
    }
  }
}
解决方案
  • "null_value": 1.0 将空值设置成 1;
DELETE ratings
PUT ratings
{
  "mappings": {
      "properties": {
        "rating": {
          "type": "float",
          "null_value": 1.0
        }
      }
    }
}

为索引的 Mapping 加入 Meta 信息

  • Mapping 设置非常重要,需要从两个维度进行考虑;
    • 功能:搜索、聚合、排序;
    • 性能:存储的开销、内存的开销、搜索的性能;
  • Mapping 设置是一个迭代的过程
    • 加入新的字段很容易(必要时需要 update_by_query);
    • 更新 / 删除字段是不允许的,需要 Reindex 重建数据;
    • 最好能对 Mapping 加入 meta 信息,更好的进行版本管理;
    • 可以考虑将 Mapping 文件上传 git 进行管理;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值