我已经知道了使用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/

10-11 10:48