我在cassandra有很多桌子,超过20亿行并且还在增加。行有一个日期字段,它遵循日期桶模式,以限制每一行。
即便如此,我在特定日期的参赛作品超过一百万。
我希望尽快阅读并处理每一天的行。我正在做的是获取com.datastax.driver.core.ResultSet
的实例并从中获取迭代器并在多个线程之间共享该迭代器。
所以,基本上我想增加读取吞吐量。这是正确的方法吗?如果没有,请建议更好的方法。
答案 0 :(得分:6)
很遗憾,你不能这样做。原因是ResultSet提供了internal paging state,用于一次检索第1行。
但你确实有选择。由于我认为您正在进行范围查询(跨多个分区的查询),因此您可以使用策略,使用token指令一次跨令牌范围提交多个查询。 Paging through unordered partitioner results中记录了一个很好的例子。
java-driver 2.0.10和2.1.5各自提供了一种从主机和splitting them检索令牌范围的机制。在TokenRangeIntegrationTest.java#should_expose_token_ranges()的java-driver集成测试中有一个如何执行此操作的示例:
PreparedStatement rangeStmt = session.prepare("SELECT i FROM foo WHERE token(i) > ? and token(i) <= ?");
TokenRange foundRange = null;
for (TokenRange range : metadata.getTokenRanges()) {
List<Row> rows = rangeQuery(rangeStmt, range);
for (Row row : rows) {
if (row.getInt("i") == testKey) {
// We should find our test key exactly once
assertThat(foundRange)
.describedAs("found the same key in two ranges: " + foundRange + " and " + range)
.isNull();
foundRange = range;
// That range should be managed by the replica
assertThat(metadata.getReplicas("test", range)).contains(replica);
}
}
}
assertThat(foundRange).isNotNull();
}
...
private List<Row> rangeQuery(PreparedStatement rangeStmt, TokenRange range) {
List<Row> rows = Lists.newArrayList();
for (TokenRange subRange : range.unwrap()) {
Statement statement = rangeStmt.bind(subRange.getStart(), subRange.getEnd());
rows.addAll(session.execute(statement).all());
}
return rows;
}
您基本上可以生成语句并以异步方式提交它们,上面的示例只是一次迭代语句。
另一种选择是使用spark-cassandra-connector,它基本上是以封面和非常有效的方式做到这一点。我发现它很容易使用,你甚至不需要设置一个火花簇来使用它。有关如何使用Java API的信息,请参阅this document。