数据模型是对描述数据、数据联系、数据语义和一致性约束进行标准化的抽象模型,是为存储在数据库中的资源创建和分析数据模型的过程。
数据建模主要目的是表示系统内的数据类型、对象之间的关系及其属性,有助于了解需要哪些数据以及应如何组织数据。
1.常见的直线思维的建模中可能的问题:
①大量的冗余的字符串字段,浪费空间
②没有设置合适的分词应对特定情况
③面临大数据量存储空间上限压力,而设计时没有考虑。删数据用delete by query,会占用更多的磁盘空间
2.按业务角度建模:
①业务分类要细分,对不同业务渠道,不同业务场景等建立不同的索引。
②为了避免跨索引检索的复杂性问题,对含义相似的字段要统一字段名称。
③使用别名和模板来管理多索引
3.按数据量角度建模:
时序性数据(日志、舆情、定时任务结果集)应当按时间切分索引。这样做灵活,方便删除,方便设置热点数据。
4.基于setting建模:
①分片和副本设置:
由于主分片个数number_of_shards在创建后不能修改,副本数number_of_replicas创建后可以修改。所以主分片设计时要考虑业务发展的需要和集群节点的规模,通常设置为数据节点的 1 倍或者 1~3 倍之间的值。普通业务场景建议至少设置一个副本。
②refresh_interval的设置:
它使得数据由 index buffer 的堆内存缓存区刷新到堆外内存区域,形成segment,以使得搜索可见。默认值1s。在实际业务场景里,如果写入的数据不需要近实时搜索可见,可以适当地在模板、索引层面调大这个值,当然也可以动态调整,比如调整为 30s 或者 60s。
③max_result_window的设置:
按照from+size的方式查询,from越大速度越慢。如果是搜索的场景,建议按照默认的实现,因为大部分业务场景都只需要关联度高的数据。
如果需要向后翻页查询,推荐 search_after 查询方式。如果需要全量遍历或者全量导出数据,推荐 scroll 查询方式。
④管道预处理:是一个非常好用的功能,在5.x加入,在需要的时候考虑进去使用作为最佳实践。
5.基于mapping建模:
①字段命名要规范
②字段类型要合理:
如能用int,就不用long、float等。字符串考虑是keyword还是text,而不是不考虑直接用默认。思考range是不是能转化为固定的值。等等
③分词器要灵活
④multi_fields类型:考虑一个字段需要多种类型的情况
6.复杂索引问题的方案:
①宽表:设置冗余字段减少关联查询
②nested 方案适用场景:1 对少量,子文档偶尔更新、查询频繁的场景。如果需要索引对象数组并保持数组中每个对象的独立性,则应使用嵌套 Nested 数据类型而不是对象 Oject 数据类型。Nested 嵌套可以使查询慢几倍。
③join 父子文档方案适用场景:子文档数据量要明显多于父文档的数据量,存在 1 对多量的关系;子文档更新频繁的场景。Join 父子关系可以使查询慢数百倍
④业务层面处理:多次查询放在业务层逻辑中
