美文网首页
ElasticSearch | 数据建模 | 最佳实践

ElasticSearch | 数据建模 | 最佳实践

作者: 乌鲁木齐001号程序员 | 来源:发表于2020-06-01 03:42 被阅读0次

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

    • 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 - 新增字段不会被索引,也不会保存在 _source 中,文档写入失败;
    使用 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
              }
            }
          }
        }
      }
    }
    
    • 写入数据;
    PUT cookie_service/_doc/1
    {
     "url":"www.google.com",
     "cookies":[
        {
          "name":"username",
          "keywordValue":"tom"
        },
        {
          "name":"age",
          "intValue":32
        }
       ]
     }
    
    • 使用 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 进行管理;

    相关文章

      网友评论

          本文标题:ElasticSearch | 数据建模 | 最佳实践

          本文链接:https://www.haomeiwen.com/subject/aggdzhtx.html