背景
在使用Impala做自助分析的过程中,我们经常发现自定义属性的需求,通常情况下用户会将这种不确定key的字段全部塞到一个MAP字段中,然后通过Impala的复杂结构查询语法进行查询,目前Impala只支持Parquet格式表的schema中使用复杂数据类型(包括STRUCT、ARRAY和MAP),查询语法可以参考 Impala复杂类型语法,但是它存在两个弊端:语法不兼容hive和查询性能不理想。第一个问题是由于特定的实现方式导致的,第二个问题则是由于parquet存储MAP类型的字段决定的。那么有没有办法提升用户的这种查询需求和简化查询SQL的写法呢?
JSON UDF VS. MAP
为了避免MAP在impala中复杂的使用方式和性能不好的问题,我们一般建议使用JSON字符串的方式代替map存储表达的字段内容,毕竟json能够完全表示出MAP的语义,而开发一般使用JAVA实现,也比较方便生成JSON格式的数据。通过使用json解析的UDF来抽取其中想要的字段,我们首先使用了一个开源的JSON UDF的实现 ,这个开源的实现使用了rapidjson作为json解析器,它的使用方法类似于hive的get_json_object,函数定义如下:
STRING get_json_object(STRING, STRING)
第一个参数为输入的json字符串,第二个参数是需要解析的内容,该内容通过如下方式解析:
- $ : Root object(表示根节点)
- . : Child operator(表示父节点和子节点的分隔符)
- [] : Subscript operator for array(访问数组)
-
- : Wildcard for [] (通配符)
例如对于一个{“hello”, “world”}的JSON字段(字段名为col)想要提取hello的值,可以使用get_json_object(col, “$.hello”)得到的值就是”world”。
通过它可以提取map中想要的字段,它的实现原理是用rapidjson解析输入的第一个参数,解析成Document之后再通过解析第二个参数选