在Spark SQL中的一个查询中使用多个collect_list

时间:2016-11-03 17:12:44

标签: scala apache-spark hive apache-spark-sql

我有以下数据框data

root
 |-- userId: string 
 |-- product: string 
 |-- rating: double

以及以下查询:

val result = sqlContext.sql("select userId, collect_list(product), collect_list(rating) from data group by userId")

我的问题是,聚合数组中的productrating是否相互匹配?也就是说,同一行中的productrating在聚合数组中是否具有相同的索引。

更新: 从Spark 2.0.0开始,可以对struct类型执行collect_list,因此我们可以在组合列上执行一个collect_list。但是对于2.0.0之前的版本,人们只能在原始类型上使用collect_list

1 个答案:

答案 0 :(得分:9)

我相信没有明确保证所有阵列都具有相同的顺序。 Spark SQL使用多个优化,并且在某些条件下无法保证所有聚合同时进行调度(一个示例是使用SELECT userId, collect_list(struct(product, rating)) FROM data GROUP BY userId 进行聚合)。由于交换(shuffle)导致不确定的顺序,理论上订单可能会有所不同。

因此,虽然它应该在实践中起作用,但它可能存在风险并且会引入一些难以发现的错误。

如果您使用Spark 2.0.0或更高版本,则可以使用WITH tmp AS ( SELECT * FROM data DISTRIBUTE BY userId SORT BY userId, product, rating ) SELECT userId, collect_list(product), collect_list(rating) FROM tmp GROUP BY userId 聚合非原子列:

function GetOrder(target: MyOrder, key: string, descriptor: any) {
    console.log(target, key, descriptor);

    const newDescriptor = Object.assign({}, descriptor);

    newDescriptor.value = function() {
        let metadata = Reflect.getMetadata(metadata_key, target, "order");
        console.log("metadata value is: ", metadata);
        return descriptor.value.apply(this, arguments);
    }

    console.log(newDescriptor);

    return newDescriptor;
}

如果您使用的是早期版本,则可以尝试使用显式分区并订购:

<div id = "content">
</div>