背景
上一篇《基于ElasticSearch的OLAP框架思路》简单介绍了ES的存储结构,本文对ES的数据建模做些整理,是对上文的补充。
数据建模
范式化设计
在关系型数据库中会强调范式化设计(Normalization),其主要目标是“减少不必要的更新”,但也就带了一个问题“查询缓慢”,因为数据库越范式化,就需要Join越多的表。
关系型数据库设计时,通常设计时做到3NF,但在必要时进行数据的冗余。以下是范式的简要描述:
- 1NF——消除非主属性对键的部分函数依赖
- 2NF——消除非主属性对键的传递函数依赖
- 3NF——消除主属性对键的传递函数依赖
- BCNF——主属性不依赖主属性
反范式化设计
范式化的另一个好处呢,就是减少了存储空间(也有可能是早些年存储成本大,才有了范式化设计)。但在存储越来越便宜和数据量越来越大,查询需求也越来越多的情况下,关系型数据库就越来越受到挑战,非关系型数据库不断的涌现出来。其实可以理解来范式化设计与反范式化设计的交锋和解决不同的应用场景问题。
反范式化设计(Denormalization),就是尽量不去使用关联关系,而是在文档中保存存冗余的数据,将数据扁平化(Flattening)。这样做的优点很明显,就是数据读取性能好,缺点也很明显,不适合在数据频繁修改的场景,一条数据改动,会引起很多数据的更新,对数据一致性提出更高要求。
ES数据库设计时通常会采用反范式化设计,因为ES并不擅长处理关联关系,一般采用以下四种方法来处理关联:
- 对象类型(Object)
- 嵌套对象(Nested Object)
- 父子关系(Parent/Child)
- 应用端关联
其实应用端关联不属于ES设计的部分,在本文中不再赘述,另外基础的数据类型对数据建模影响不大,需要时参看ES相关文档进行设计即可。
对象类型
ES采用JSON的文档化存储,而JSON文档天然就是有层级的,文档内可以包含对象(普通对象和数组对象),如果存储数组对象并需要进行查询或统计时,计算结果可能是错误的,这个时候就需要用到嵌套对象。
嵌套对象
嵌套对象是对象类型的一个特例,允许对象数组中的对象独立索引,Nested文档会被保存在两个Lucene文档中,在查询时做Join处理,因此每次更新,需要重新索引整个对象(包括根对象和嵌套对象)。
父子关系
ES提供了类似关系型数据库中Join的实现。使用Join数据类型实现,可能过维护Parent/Child的关系,从而分离两个对象。这样呢,父文档和子文档是两个独立的文档,更新父文档时无需重新索引子文档,子文档被添加,更新或者删除时也不会影响父文档和其他的子文档。需要额外的内存维护,读取性能相对差。
最佳实践
应用场景
- 对象类型,优先考虑。
- 嵌套对象,当数据包含多数值对象,同时有查询需求
- 父子关系,当关联文档更新非常频繁时。
避免过多字段
- 过多字段不容易维护,Mapping保存在Cluster State中,数据量过大时会对集群性能造成影响。删除或修改需要reindex。
- 默认1000,可通过index.mapping.total_fields.limit来进行设置
- Dynamic默认是打开的,只要有新的字段进入Mapping就会更新,导致文档膨胀,可能通过设置Stick,采用Nested Object和Key Value来解决这个问题。
避免正则查询
- 正则,通配符查询,特别是前缀查询,性能不好。可以采用Netest字段方式将一个字段拆分成多个字段。
避免空值引起的聚合不准
null值无论是在关系型数据库,还是在非关系型数据库,都是被特殊对待的。在ES中可以通过设置null_value,来指定字段为null时的默认值。
为索引的Mapping加入Meta信息
Mappings设置无论从功能,还是性能方面来说都非常的重要,Mappings的每一次变更的都可能造成功能和性能的变化或者数据迁移,因此需要增加Meta(版本)信息并利用版本化控制工具(如Git)进行管理。
重建索引
可以通过update_by_query来对历史数据的新增字段进行索引的重建。因为ES不允许对已有字段修改数据类型,只能通过reindex的方式将一个索引重新索引到一个新的索引上,但可能通过指定别名的方法来使得减少应用程序的修改。
数据预处理
对于OLAP来说,数据的清洗和转换是不可避免的,而通过Ingest Node和Painless Script。相当于关系型数据库的存储过程或函数。
Ingest Node:Pipeline&Processor(可实现插件)。
Painless Script:默认缓存100个。
参考资料
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
《Elasticsearch核心技术与实战》
