无法使用timeuuid作为主键执行timeseries查询

f5emj3cl  于 2021-06-14  发布在  Cassandra
关注(0)|答案(1)|浏览(458)

我的目标是在给定的时间范围(fromdate<stats\u date\u id<todate)内,对每个不同的提供者的发送的消息和发送的电子邮件进行求和,但不指定提供者的id。换句话说,我需要知道指定时间范围内的任何和所有提供者,并对其发送的消息和发送的电子邮件进行求和。
我有一个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 .
我猜你不能有一个主键并且在上面做日期范围搜索?如果是这样,这种查询的正确方法是什么?

am46iovg

am46iovg1#

因此,虽然没有使用express cassandra,但我可以告诉您,在分区键上运行范围查询是一个很难回答的“否”。原因是cassandra无法为该查询确定单个节点,因此它必须轮询每个节点。由于这实际上是跨多个节点对表进行的完整扫描,因此会抛出该错误以防止运行错误的查询。
但是,您可以对集群键运行范围查询,前提是您要对它之前的所有键进行筛选。在你的情况下,如果我读对了,你的主键看起来像: PRIMARY KEY (stats_date_id, created_at) 主键定义有两个问题: stats_date_id 是timeuuid。这对于数据分发非常有用。但查询灵活性太差了。实际上,您需要提供确切的timeuuid值来返回特定分区的数据。由于timeuuid具有毫秒精度,您需要知道精确到毫秒的查询时间。也许你有能力做到这一点,但通常这并不意味着一个好的分区键。
分区下面有行吗( created_at )将不得不分享准确的时间,这通常会导致许多1:1基数比为partition:clustering keys.
我的建议是在基数稍低的日期列上进行分区。想想在一个特定的时间范围内通常保存了多少提供者消息。还要选择一些不会同时存储太多提供者消息的内容,因为您不希望未绑定的分区增长(cassandra的硬限制是每个分区20亿个单元)。
可能是这样的: PRIMARY KEY (week,created_at) 因此,您的cql查询可以如下所示:

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

热释光;博士;
一个时间段上的分区不如ms上的分区精确,但是它足够大,可以满足您通常的查询。
在分区内的第一个集群键上应用范围过滤器。

相关问题