我需要一个查询,列出spark中唯一的复合分区键
CASSANDRA中的查询:SELECT DISTINCT key1, key2, key3 FROM schema.table;
非常快,但是在RDD中使用相同类型的数据过滤器或者spark.sql在比较中检索结果的速度非常慢。
e.g。
---- SPARK ----
var t1 = sc.cassandraTable("schema","table").select("key1", "key2", "key3").distinct()
var t2 = spark.sql("SELECT DISTINCT key1, key2, key3 FROM schema.table")
t1.count // takes 20 minutes
t2.count // takes 20 minutes
---- CASSANDRA ----
// takes < 1 minute while also printing out all results
SELECT DISTINCT key1, key2, key3 FROM schema.table;
表格格式如下:
CREATE TABLE schema.table (
key1 text,
key2 text,
key3 text,
ckey1 text,
ckey2 text,
v1 int,
PRIMARY KEY ((key1, key2, key3), ckey1, ckey2)
);
在查询中不会引发使用cassandra优化吗? 如何有效地检索这些信息?
答案 0 :(得分:6)
不会在其查询中引发使用cassandra优化吗?
是。但是SparkSQL只有列修剪和谓词下推。在RDD中它是手动的。
如何有效地检索这些信息?
由于您的请求返回得足够快,我将直接使用Java Driver来获取此结果集。
虽然Spark SQL可以提供一些基于C *的优化,但这些优化通常仅限于使用DataFrame接口时的谓词下推。这是因为框架仅向数据源提供有限的信息。我们可以通过对您编写的查询执行 explain 来看到这一点。
scala> spark.sql("SELECT DISTINCT key1, key2, key3 FROM test.tab").explain
== Physical Plan ==
*HashAggregate(keys=[key1#30, key2#31, key3#32], functions=[])
+- Exchange hashpartitioning(key1#30, key2#31, key3#32, 200)
+- *HashAggregate(keys=[key1#30, key2#31, key3#32], functions=[])
+- *Scan org.apache.spark.sql.cassandra.CassandraSourceRelation test.tab[key1#30,key2#31,key3#32] ReadSchema: struct<key1:string,key2:string,key3:string>
因此,您的Spark示例实际上将分为几个步骤。
为什么这些都没有被推到C *?这是因为Datasource(本例中为CassandraSourceRelation)未提供有关查询的 Distinct 部分的信息。这只是Spark目前工作方式的一部分。 Docs on what is pushable
使用RDDS,我们为Spark提供了一套直接的指令。这意味着如果你想要推倒一些东西,它必须是manually specified。让我们看一下RDD请求的调试输出
scala> sc.cassandraTable("test","tab").distinct.toDebugString
res2: String =
(13) MapPartitionsRDD[7] at distinct at <console>:45 []
| ShuffledRDD[6] at distinct at <console>:45 []
+-(13) MapPartitionsRDD[5] at distinct at <console>:45 []
| CassandraTableScanRDD[4] at RDD at CassandraRDD.scala:19 []
问题在于,您的“不同”调用是对RDD的通用操作,而不是Cassandra特有的。由于RDD要求所有优化都是显式的(你输入的内容是什么)Cassandra从不听说过对“Distinct”的这种需求,我们得到的计划几乎与我们的Spark SQL版本相同。进行全面扫描,将所有数据从Cassandra序列化为Spark。做一个Shuffle然后返回结果。
使用SparkSQL,如果不向Catalyst(SparkSQL / Dataframes Optimizer)添加新规则,就可以了解Cassandra可以处理一些不同的调用服务器级别。然后需要为CassandraRDD子类实现它。
对于RDD,我们需要添加一个功能,如已存在的where
,select
和limit
,调用Cassandra RDD。可以添加新的Distinct
来电here,但只有在特定情况下才允许这样做。这个功能目前在SCC中不存在,但可以相对容易地添加,因为它所做的就是将DISTINCT
添加到requests并可能添加一些检查以确保它是{{1} }} 那讲得通。
由于我们知道我们想要的确切CQL请求,因此我们可以始终直接使用Cassandra驱动程序来获取此信息。 Spark Cassandra连接器提供了我们可以使用的驱动程序池,或者我们可以本身使用Java驱动程序。要使用池,我们会做类似的事情
DISTINCT
然后将结果并行化,如果需要进一步的Spark工作。如果我们真的想要分发它,那么有必要将函数添加到Spark Cassandra Connector中,如上所述。
答案 1 :(得分:2)
只要选择分区键,就可以使用CassandraRDD的.perPartitionLimit
功能:
val partition_keys = sc.cassandraTable("schema","table").select("key1", "key2", "key3").perPartitionLimit(1)
之所以有效,是因为根据SPARKC-436
select key from some_table per partition limit 1
得到与
相同的结果 select distinct key from some_table
答案 2 :(得分:0)
Distinct表现不佳。 这里有一些很好的答案: How to efficiently select distinct rows on an RDD based on a subset of its columns`
您可以使用toDebugString来了解您的代码有多少数据随机播放。