我已经了解了使用IN(https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlSelect.html#cqlSelect__selectInNot)的反模式。
但是如果我有一组属于同一个TokenRnage的分区键怎么办?
所以,假设我们有下一个代码:
public ResultSet getDataForFirstTokenRange(List<String> initialKeys)
Cluster cluster = Cluster.builder().addContactPoints(DEFAULT_SEEDS)
.withClusterName(DEFAULT_CLUSTER_NAME).build();
Metadata meta = cluster.getMetadata();
Set<TokenRange> tokens = meta.getTokenRanges();
TokenRange firstTr = tokens.iterator().next();
List<String> filteredKeys = filterKeysForToken(firstTr, initialKeys, meta)
return session.execute(
"select * from MY_TABLE where key IN (" +
String.join(
", ",
filteredKeys.stream()
.map(key -> "'" + key + "'")
.collect(Collectors.toList())
) +
")"
);
}
private List<String> filterKeysForToken(TokenRange tr, List<String> keys, Metadata meta) {
return keys.stream()
.filter(key -> {
Token token = meta.newToken(TypeCodec.varchar().serialize(
key,
ProtocolVersion.NEWEST_SUPPORTED
));
return tr.contains(token);
})
.collect(Collectors.toList());
}
所以,这里我过滤了分区键的初始列表,因此结果列表只属于一个TokenRange。
然后我查询。
所以问题是,这里会出现性能问题吗? 如果没有,这种方法会比为每个分区密钥执行单独的查询更好吗?
答案 0 :(得分:1)
我假设您已经知道分区键告诉Cassandra存储哪些节点数据。
从功能上讲,拥有多个异步查询和一个IN子句是相同的:你将击中集群中的一个节点。但是,具有IN子句应该是主要的性能损失,因为协调器在将答案返回给客户端之前等待所有数据可用。相反,如果您发出多个异步查询,则会有单独的流向客户端,每个查询一个,并且您应该能够更快地处理数据。