Avro 模式演化与排序
Avro 模式的演化
Avro的读操作不同于写操作,读操作可以动态的控制要取出的数据,而这种动态,在Avro中被称为演化。
#####演化一:读取新增字段 Avro 可以读取预定模式所规定格式的文件数据,也可以支持模式的演化。例如,我们将上篇文章引用的模式 StringPair.avsc 再加上一个字段,形成一个新模式:
{ "type": "record", "name": "StringPair", "doc": "A pair of strings.", "fields": [ {"name": "left", "type": "string"}, {"name": "right", "type": "string"}, {"name" : "num", "type" : "int"}, {"name" : "description", "type" : ["string",null],"default":"null"} ] }
使用这个新模式重新读取前面序列化的数据,发现依旧能够正常的读取,这是因为给 description 字段指定了默认值 “” ,供 Avro 在读取没有定义的字段的纪录时使用。如果在这 schema 中没有 default 属性,读取旧数据时就会发生错误。
演化二: 读取部分字段
Avro 还支持忽略部分数据去读取。在很多应用中我们只需要大量字段中的某一部分,这时我们就可以使用 Avro中的投影去读取数据。例如我们要只读取 StringPair.avsc 中的 right 字段
{ "type": "record", "name": "StringPair", "doc": "A pair of strings.", "fields": [ {"name": "right", "type": "string"} ] }
模式解析规则可以直接解决模式由一个版本演化为另一个版本时可能产生的问题,Avro规范中对所有的Avro类型均有详细的说明。
演化三: 别名
别名允许在读取Avro数据的模式与写入Avro数据的模式时使用不同的名称。例如下面读数据可以使用新的字段名称而不是写入时字段的名称,来读取 StringPair 的数据。
{ "type": "record", "name": "StringPair", "doc": "A pair of strings.", "fields": [ {"name": "R", "type": "string","aliases":"right"} ] }
注意,别名的主要作用是讲写入模式转换为读取模式,但是别名对读程序是不可见的。也就是说在上面的程序中读程序无法再使用 right 字段,因为它已经被转换成了 R 字段。
Avro 模式的排序
Avro定义了对象的排序方式,其大多数数据类型与期望的排序方式相符合,比如数值类型按照数值的升序进行排列。但还有一些类型的排序就会让人很无奈,如枚举通过符号的定义而非符号字符串的值来排序。 除了record类型之外其它类型均按照Avro规范中预定的规则来进行排序,这些规则用户无法进行改写。但对于纪录,可以指定order属性来控制排列的顺序。order属性可以有三个值:升序(ascending 默认)、降序(descending)或忽略(ignore)
{ "type": "record", "name": "StringPair", "doc": "A pair of strings.", "fields": [ {"name": "left", "type": "string","order":"ignore"}, {"name": "right", "type": "string","order":"ascending"}, {"name" : "num", "type" : "int"} ] }
而且Avro是直接基于二进制数据进行比较的,其直接对字节流进行操作,比较的过程是无比高效的。Avro的排序逻辑主要是用于MapReduce中,实现数据文件的并行排序。下一篇我们将介绍 Avro MapReduce这个不使用传统的Writable而使用新的数据序列化方式的并行计算方式。