我已经知道了使用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。
然后,我进行查询。
所以问题是,这里是否会有性能问题?
如果不是,这种方法是否比对每个分区键执行单独的查询更好?
最佳答案
我假设您已经知道分区键告诉Cassandra存储节点数据的位置。
从功能上讲,具有多个异步查询和一个IN子句是相同的东西:您将在集群中命中一个节点。但是,拥有IN子句应该会严重影响性能,因为协调器在将答案返回给客户端之前会等待所有数据可用。相反,如果您发出多个异步查询,则您有分别的流向客户端,每个查询都有一个流,并且您应该能够更快地处理数据。
关于java - 在SQL中将IN条件用于分区键而不会降低性能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44032883/