我很好奇星火如何使用get_json_object
方法,以及我是否正确地使用了它。假设我有一个string类型的列data
(JSON编码的),每一行的值都相当大(~1MB)。
如果我想检索和处理参数的子集,我可以很容易地做到:
param_a = get_json_object("data", "$.my.param.a").cast("int")
param_b = get_json_object("data", "$.my.param.b").cast("int")
my_sum = param_a + param_b
星火会自动派生出它只需要在内部解码一次JSON,然后再使用该状态,还是它会对get_json_object
的每个调用进行解码?
另外,我也可以使用from_json
并在定义良好的模式中检索:
_schema = StructType().add("a", IntegerType()).add("b", IntegerType())
params = from_json(get_json_object("data", "$.my.param"), _schema)
my_sum = params["a"] + params["b"]
因此,我的问题是:这些方法在性能上是否具有可比性,和/或是否有其他原因可以使用一种方法而另一种方法呢?
发布于 2020-09-04 09:34:12
我对Apache这一部分的理解是相当有限的,但我想分享一下get_json_object
的代码,这些代码可以提供更多的信息(并且可能会给出一个非常有用的答案)。
tl;dr:我建议在访问多个JSON字段时使用from_json(get_json_object(...), ...)
,以避免更昂贵的get_json_object
(内存方面)。
(我在使用Scala,但这并不重要,只是它更接近“裸金属”)
// let's use a very simple query to demo the concept
val q = sql("""SELECT get_json_object('{"a":"b"}', '$.a'), get_json_object('{"aa":"bb"}', '$.aa')""")
scala> q.explain
== Physical Plan ==
*(1) Project [b AS get_json_object({"a":"b"}, $.a)#10, bb AS get_json_object({"aa":"bb"}, $.aa)#11]
+- *(1) Scan OneRowRelation[]
正如您可能已经注意到的,物理查询计划使用两个不同的get_json_object
表达式(一个使用#10
,另一个使用#11
唯一标识符)。
get_json_object
只是掩护下的GetJsonObject催化剂表达式,而评估方法则是所有魔术发生的地方。
在某种程度上,eval
做CreateJacksonParser.utf8String(jsonFactory, jsonStr)
。它使用这个jsonFactory
值,由于它是val
和对象SharedFactory的一部分,所以它恰好在任何Java/Python/JVM代码之间共享。在Scala中,关键字object
在星火执行器(单个JVM)上的所有任务中提供一个实例。这当然是共享实例,但这只是一个工厂(而不是JSON解析器本身)。
我的理解是,每次请求一个新的JSON解析器时,都会创建一个新的解析器(可能是因为它是一个可变的“猛兽”?)。你必须查阅杰克逊的JsonFactoryBuilder才能找到答案。
发布于 2020-09-04 05:56:54
所以我写了一个测试(GitHub上的要点)来测试它。基本上,通过以下变量执行我前面描述的设置:
使用具有1KB数据JSON编码的字符串内容(和500个副本)的100行的8个参数,结果如下:
{<function _method_b at 0x7fb73d30e200>: 0.16155768394470216,
<function _method_a at 0x7fb73d30e320>: 0.22132105827331544}
因此,在这种情况下,在执行大约25%的模式方面有了改进。
此外:
{<function _method_b at 0x7f43d7dc4200>: 0.15471874809265138,
<function _method_a at 0x7f43d7dc4320>: 0.14935027599334716}
因此:我的结论是,如果您想要解释一个结构的许多参数,那么强制模式的性能就会有所提高,但是如果只是少数几个参数,那么只使用get_json_object
和强制转换就可以达到同样的性能(而且更容易读/写)。
https://stackoverflow.com/questions/63730434
复制相似问题