Невозможно выполнить запрос временных рядов, используя timeuuid в качестве первичного ключа. - PullRequest
1 голос
/ 19 сентября 2019

Моя цель состоит в том, чтобы сделать сумму messages_sent и emails_sent для каждого значения DISTINCT provider_id для заданного временного диапазона (fromDate

У меня есть таблица Cassandra, использующая схему express-cassandra (в Node.js) какследует:

module.exports = {
  fields: {
    stats_provider_id: {
      type: 'uuid',
      default: {
        '$db_function': 'uuid()'
      }
    },
    stats_date_id: {
      type: 'timeuuid',
      default: {
        '$db_function': 'now()'
      }
    },
    provider_id: 'uuid',
    provider_name: 'text',
    messages_sent: 'int',
    emails_sent: 'int'
  },
  key: [
    [
      'stats_date_id'
    ],
    'created_at'
  ],
  table_name: 'stats_provider',
  options: {
    timestamps: {
      createdAt: 'created_at', // defaults to createdAt
      updatedAt: 'updated_at' // defaults to updatedAt
    }
  }
}

Чтобы все заработало, я надеялся, что это будет так же просто, как сделать следующее:

let query = {
    stats_date_id: {
      '$gt': db.models.minTimeuuid(fromDate),
      '$lt': db.models.maxTimeuuid(toDate)
    }
  };
let selectQueries = [
    'provider_name',
    'provider_id',
    'count(direct_sent) as direct_sent',
    'count(messages_sent) as messages_sent',
    'count(emails_sent) as emails_sent',
  ];
  // Query stats_provider table
  let providerData = await db.models.instance.StatsProvider.findAsync(query, {select: selectQueries});

Это, однако, жалуется на необходимость фильтрации результатов: Error during find query on DB -> ResponseError: Cannot execute this query as it might involve data filtering and thus may have unpredictable performance.

Я полагаю, у вас не может быть первичного ключа, и поиск по диапазону дат на нем?Если да, то каков правильный подход к такого рода запросам?

1 Ответ

2 голосов
/ 19 сентября 2019

Так что, хотя я и не использовал Express-Cassandra, я могу вам сказать, что выполнение запроса диапазона для вашего ключа раздела - это жесткое «нет».Причина этого в том, что Cassandra не может определить отдельный узел для этого запроса, поэтому она должна опрашивать каждый узел.Поскольку это, по сути, полная проверка вашей таблицы по нескольким узлам, она выдает эту ошибку, чтобы предотвратить выполнение неверного запроса.

Однако вы можете выполнить запрос диапазона на ключе кластеризациипри условии, что вы фильтруете все ключи до этого.В вашем случае, если я правильно понял, ваш ПЕРВИЧНЫЙ КЛЮЧ выглядит следующим образом:

PRIMARY KEY (stats_date_id, created_at)

Определение первичного ключа будет проблематичным по двум причинам:

  1. stats_date_id - это TimeUUID.Это отлично для распространения данных.Но это отстой для гибкости запросов.На самом деле вам нужно будет указать точное значение TimeUUID для возврата данных для определенного раздела.Поскольку TimeUUID имеет точность в миллисекундах, вам необходимо знать точное время запроса с точностью до миллисекунды .Может быть, у вас есть возможность сделать это, но обычно это не подходит для хорошего ключа раздела.

  2. Любые строки под этим разделом (created_at) должны будут разделить этот точныйвремя, которое обычно приводит к большому количеству коэффициентов кардинальности 1: 1 для раздела: ключи кластеризации.

Мой совет по исправлению этого - разделить столбец даты, который имеет немного меньшую величинууровень мощностиПодумайте о том, сколько сообщений провайдера обычно сохраняется в течение определенного периода времени.Также выберите что-то, что не будет хранить слишком много сообщений провайдера вместе, так как вы не хотите увеличивать несвязанный раздел (у Cassandra жесткое ограничение в 2 миллиарда ячеек на раздел).

Таким образом, ваши запросы CQL могут выглядеть примерно так:

SELECT * FROM stats_provider
WHERE week='201909w1'
  AND created_at > '20190901'
  AND created_at < '20190905';

TL; DR;

  1. Разделение во временном интервале отсутствуетс точностью до мс, но достаточно большой, чтобы удовлетворить ваш обычный запрос.
  2. Примените фильтр диапазона к первому ключу кластеризации, в пределах раздела.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...