date分区大小10gb高效读取

ffdz8vbo  于 2021-06-14  发布在  Cassandra
关注(0)|答案(1)|浏览(368)

我们使用的是cassandra datastax 6.0和spark enabled。我们每天都有10gb的数据。所有查询都基于日期。我们有一张40列的大table。我们计划使用spark生成报告。设置此数据的最佳方法是什么。因为我们每天都在获取数据,并且在一个表中保存了大约一年的数据。
我们尝试使用不同的分区,但大多数密钥都是基于日期的。
没有代码只是需要建议
我们的查询应该足够快。我们有256gb的ram和9个节点。44核cpu。

watbbzwu

watbbzwu1#

将数据组织在每日分区中并不是很好的设计——在这种情况下,只有rf节点在写入数据的一天中,然后在生成报告的时候才是活动的。
因为您将只从spark访问该数据,所以可以使用以下方法-使用一些bucket字段作为分区键,例如,使用统一生成的随机数,将timestamp作为集群列,或者使用其他方法 uuid 记录唯一性保证栏,如下所示:

create table test.sdtest (
  b int,
  ts timestamp,
  uid uuid,
  v1 int,
  primary key(b, ts, uid));

其中 b 应该选择不太大也不太小的分区,这样才能有效地读取它们。
然后我们可以像这样运行spark代码:

import org.apache.spark.sql.cassandra._
val data = spark.read.cassandraFormat("sdtest", "test").load()
val filtered = data.filter("ts >= cast('2019-03-10T00:00:00+0000' as timestamp) AND ts < cast('2019-03-11T00:00:00+0000' as timestamp)")

这里的诀窍是,我们使用随机分区键跨节点分发数据,因此所有节点都将在写入数据和生成报告期间处理负载。
如果我们研究spark代码的物理计划(格式化为可读性):

== Physical Plan ==

* Scan org.apache.spark.sql.cassandra.CassandraSourceRelation [b#23,ts#24,v1#25]

PushedFilters: [*GreaterThanOrEqual(ts,2019-03-10 00:00:00.0),
  *LessThan(ts,2019-03-11 00:00:00.0)], ReadSchema: struct<b:int,ts:timestamp,v1:int>

我们可以看到,这两个条件都将被推送到cql级别的dse—这意味着spark不会将所有数据加载到内存中并对其进行过滤,而是所有过滤都将在cassandra中进行,并且只返回必要的数据。而且因为我们在多个节点之间传播请求,读取可能比读取一个巨大的分区更快(需要测试)。这种设计的另一个好处是,使用spark可以很容易地删除旧数据,如下所示:

val toDel = sc.cassandraTable("test", "sdtest").where("ts < '2019-08-10T00:00:00+0000'")
toDel.deleteFromCassandra("test", "sdtest", keyColumns = SomeColumns("b", "ts"))

在这种情况下,spark将执行非常有效的范围/行删除,从而生成较少的逻辑删除。
p、 建议使用dse版本的Spark连接器,因为它可能有更多的优化。
p、 理论上,我们可以合并 ts 以及 uid 合二为一 timeuuid 列,但我不确定它是否适用于Dataframe。

相关问题