我正在根据分区密钥的令牌范围从cassandra节点选择所有记录。
代码如下:
public static synchronized List<Object[]> getTokenRanges(
final Session session) {
if (cluster == null) {
cluster = session.getCluster();
}
Metadata metadata = cluster.getMetadata();
return unwrapTokenRanges(metadata.getTokenRanges());
}
private static List<Object[]> unwrapTokenRanges(Set<TokenRange> wrappedRanges) {
final int tokensSize = 2;
List<Object[]> tokenRanges = new ArrayList<>();
for (TokenRange tokenRange : wrappedRanges) {
List<TokenRange> unwrappedTokenRangeList = tokenRange.unwrap();
for (TokenRange unwrappedTokenRange : unwrappedTokenRangeList) {
Object[] objects = new Object[tokensSize];
objects[0] = unwrappedTokenRange.getStart().getValue();
objects[1] = unwrappedTokenRange.getEnd().getValue();
tokenRanges.add(objects);
}
}
return tokenRanges;
}
``` `getTokenRanges` 给我所有节点上的所有标记范围的vnode。
然后我使用这些标记范围来查询cassandra。 `object[0]` 持有vnode的开始标记,并 `object[1]` 结束标记。
生成以下查询:
SELECT * FROM my_key_space.tablename WHERE token(id)> AND token(id)<= ;
在上面 `id` 列是分区键。
在cassandra中,不建议执行范围查询,那么,是否执行此查询?
据我所知,这个查询将只调用单个分区/vnode,而不会调用多个分区,因此不应该有任何性能问题?是这样吗?
Cassandra版本:3.x
2条答案
按热度按时间jobtbby31#
是的,与对实际分区键的普通范围查询不同,令牌范围查询确实是有效的,因为它们可以按顺序从磁盘读取(分区按顺序令牌顺序存储在磁盘上)并从同一节点读取顺序数据(相邻令牌属于同一节点)。
cassandra给您一个提示,这类查询将执行得很好,因为它不需要您使用“allow filtering”。如果您尝试对实际的分区键(而不是它的令牌)执行范围查询,则需要您添加“允许筛选”以表明您知道这将导致糟糕的性能。
5vf7fwbs2#
对令牌范围的查询是有效的,spark使用它们进行有效的数据获取。但你要记住以下几点-
getTokenRanges
将为您提供所有现有的标记范围,但有一些边缘情况-最后一个范围将是从正数到负数,代表第一个范围,因此,您的查询不会做任何事情。基本上你错过了MIN_TOKEN
第一个标记,最后一个标记和MAX_TOKEN
. spark connector根据令牌生成不同的cql语句。另外,您需要将查询路由到正确的节点-这可以通过setRoutingToken
.java代码(完整代码)中也可以使用类似的方法: