Производительность запросов на основе диапазона токенов для ключей разделов? - PullRequest
0 голосов
/ 09 января 2019

Я выбираю все записи из узлов Кассандры, основываясь на диапазоне токенов моего ключа раздела.

Ниже приведен код:

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 для всех узлов.

Тогда я использую этот диапазон токенов, чтобы запросить кассандру. object[0] содержит начальный токен vnode и object[1] конечный токен.

, который генерирует запрос ниже:

SELECT * FROM my_key_space.tablename WHERE token(id)><start token number> AND token(id)<= <end token number>;

В приведенном выше столбце id указан ключ раздела.

В Кассандре не рекомендуется выполнять диапазонные запросы. Так будет ли этот запрос выполняться?

Из того, что я знаю, этот запрос будет вызывать только отдельный раздел / vnode и не будет вызывать несколько разделов, и, следовательно, не должно быть проблем с производительностью? Это правильно?

Cassandra версия: 3.x

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Запросы по диапазонам токенов являются производительными, и Spark использует их для эффективной выборки данных. Но вам нужно помнить следующее: getTokenRanges даст вам все существующие диапазоны токенов, но есть некоторые крайние случаи - последний диапазон будет от некоторого положительного числа до отрицательного числа, которое представляет первый диапазон, и, как таковой, Ваш запрос ничего не сделает. Обычно вы пропускаете данные между MIN_TOKEN и первым токеном, а также между последним токеном и MAX_TOKEN. Spark Connector генерирует различные операторы CQL на основе токена. Кроме того, вам нужно направить запрос к правильному узлу - это можно сделать через setRoutingToken.

Аналогичный подход можно использовать в коде Java ( полный код ):

    Metadata metadata = cluster.getMetadata();
    Metadata metadata = cluster.getMetadata();
    List<TokenRange> ranges = new ArrayList(metadata.getTokenRanges());
    Collections.sort(ranges);
    System.out.println("Processing " + (ranges.size()+1) + " token ranges...");

    Token minToken = ranges.get(0).getStart();
    String baseQuery = "SELECT id, col1 FROM test.range_scan WHERE ";
    Map<String, Token> queries = new HashMap<>();
    // generate queries for every range
    for (int i = 0; i < ranges.size(); i++) {
        TokenRange range = ranges.get(i);
        Token rangeStart = range.getStart();
        Token rangeEnd = range.getEnd();
        if (i == 0) {
            queries.put(baseQuery + "token(id) <= " + minToken, minToken);
            queries.put(baseQuery + "token(id) > " + rangeStart + " AND token(id) <= " + rangeEnd, rangeEnd);
        } else if (rangeEnd.equals(minToken)) {
            queries.put(baseQuery + "token(id) > " + rangeStart, rangeEnd);
        } else {
            queries.put(baseQuery + "token(id) > " + rangeStart + " AND token(id) <= " + rangeEnd, rangeEnd);
        }
    }

    // Note: It could be speedup by using async queries, but for illustration it's ok
    long rowCount = 0;
    for (Map.Entry<String, Token> entry: queries.entrySet()) {
        SimpleStatement statement = new SimpleStatement(entry.getKey());
        statement.setRoutingToken(entry.getValue());
        ResultSet rs = session.execute(statement);
        // .... process data
   }
0 голосов
/ 09 января 2019

Да, запросы диапазона токенов запросов, в отличие от запросов обычного диапазона по фактическому ключу раздела, действительно производительны, потому что они могут читать с диска последовательно (разделы хранятся на диске в последовательном порядке токенов) и читать последовательные данные из одного и того же узла (смежные токены принадлежат одному и тому же узлу).

Cassandra дает вам подсказку, что этот тип запроса будет работать хорошо, потому что он не требует использования «РАЗРЕШИТЬ ФИЛЬТРАЦИЮ». Если бы вы попытались выполнить запрос диапазона для фактического ключа раздела (не его токена), для этого потребовалось бы добавить «РАЗРЕШИТЬ ФИЛЬТР», чтобы показать, что вы знаете, что это будет иметь плохую производительность.

...