Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cassandra 卡桑德拉和<;==&燃气轮机;不允许筛选日期上的运算符_Cassandra_Cql - Fatal编程技术网

Cassandra 卡桑德拉和<;==&燃气轮机;不允许筛选日期上的运算符

Cassandra 卡桑德拉和<;==&燃气轮机;不允许筛选日期上的运算符,cassandra,cql,Cassandra,Cql,我是cassandra的不速之客,我不明白为什么我不能按日期过滤(希望在日期之间返回结果),例如: CREATE TABLE test.service_bar( service_bar_id UUID, start_date_time timestamp, end_date_time timestamp, title varchar, message text, is_active boolean, PRIMARY KEY((start_d

我是cassandra的不速之客,我不明白为什么我不能按日期过滤(希望在日期之间返回结果),例如:

CREATE TABLE test.service_bar(
    service_bar_id UUID,
    start_date_time timestamp,
    end_date_time timestamp,
    title varchar,
    message text,
    is_active boolean,
    PRIMARY KEY((start_date_time, end_date_time))
);
那么这个工作,

  SELECT start_date_time, end_date_time, is_active, message, service_bar_id, title
  FROM test.service_bar
  WHERE start_date_time = '2019-10-30 14:10:29'  AND end_date_time = '2019-10-30 14:10:29'
  LIMIT 500;
但是这个剂量

  SELECT start_date_time, end_date_time, is_active, message, service_bar_id, title
  FROM test.service_bar
  WHERE start_date_time >= '2019-10-30 14:10:29'  AND end_date_time <= '2019-10-30 14:10:29'
  LIMIT 500;
选择开始日期时间、结束日期时间、是否活动、消息、服务条id、标题
从test.service_bar
其中开始日期时间>='2019-10-30 14:10:29'和结束日期时间
我不明白为什么我不能按日期筛选(希望在日期之间返回结果)

您看到的行为是因为:

PRIMARY KEY((start_date_time, end_date_time))
您已将
start\u date\u time
end\u date\u time
定义为复合分区键。由于Cassandra使用分布式散列来确保正确的数据分布,所以分区不是按值的顺序存储的。它们由分区键的哈希标记值存储。您可以通过使用分区键上的
标记
函数来看到这一点:

aaron@cqlsh:stackoverflow> SELECT token(start_date_time,end_date_time),start_date_time,end_date_time,service_bar_id FROM service_bar ;

 system.token(
     start_date_time,
     end_date_time)   | start_date_time                 | end_date_time                   | service_bar_id
----------------------+---------------------------------+---------------------------------+--------------------------------------
    26346508703811310 | 2019-10-30 19:10:29.000000+0000 | 2019-10-30 19:10:29.000000+0000 | 49a70440-8689-4248-b389-13b8d0373e58
  1488616260313758762 | 2019-11-01 19:10:29.000000+0000 | 2019-11-01 19:10:29.000000+0000 | b0bab610-a285-41e7-ba5c-d56f8fb12f52
  2185622653117187064 | 2019-10-30 21:10:29.000000+0000 | 2019-10-30 21:10:29.000000+0000 | 3686c6a6-fd8d-4247-b501-964363a48f63
  7727638696734890177 | 2019-10-30 20:10:29.000000+0000 | 2019-10-30 20:10:29.000000+0000 | 97fc799e-fb54-4b7f-956e-f06bcb9e9d9d

(4 rows)
这是行的默认顺序。这样做是因为每个节点负责特定的令牌范围,以确保数据尽可能均匀地分布在多节点集群中(这是通常的生产用例)。因此,CQL对如何查询分区键有一些限制。这些限制可以避免编写错误的查询…例如不允许对分区键进行范围查询

我如何在Cassandra中进行此类查询

这还应该告诉您,您应该构建表和查询,以确保它们可以通过对单个节点的请求来实现。考虑到这一点,您的用例只有在更改分区键时才会真正起作用

开发团队实现像您这样的解决方案的一种方法是使用一种称为“时间bucketing”的建模技术,或者有时只是“bucketing”。在这种情况下,假设您每月编写的条目不会超过几千条。也许情况并非如此,但我将在本例中使用它。然后我可以按月分区,然后使用
\u time
列作为集群键

CREATE TABLE stackoverflow.service_bar_by_month (
    month_bucket int,
    start_date_time timestamp,
    end_date_time timestamp,
    is_active boolean,
    message text,
    service_bar_id uuid,
    title text,
    PRIMARY KEY (month_bucket, start_date_time, end_date_time)
) WITH CLUSTERING ORDER BY (start_date_time DESC, end_date_time DESC);
这将按照
月日时段的值将所有行存储在一起,并且在每个分区内,这些行将按照
开始日期时间
结束日期时间
降序排列。现在,这项工作:

aaron@cqlsh:stackoverflow> SELECT start_date_time, end_date_time, is_active, message, service_bar_id, title
                 ... FROM service_bar_by_month
                 ... WHERE month_bucket = 201910 AND start_date_time >= '2019-10-30 14:10:29'  AND start_date_time <= '2019-10-31 23:59:59';

 start_date_time                 | end_date_time                   | is_active | message           | service_bar_id                       | title
---------------------------------+---------------------------------+-----------+-------------------+--------------------------------------+--------
 2019-10-30 21:10:29.000000+0000 | 2019-10-30 21:10:29.000000+0000 |      True | This is an alert3 | eae5d3be-b2b2-40a1-aa28-0412fe9c18e6 | alert3
 2019-10-30 20:10:29.000000+0000 | 2019-10-30 20:10:29.000000+0000 |      True | This is an alert2 | af4ec72f-7758-42ef-b731-8d08f8a00006 | alert2
 2019-10-30 19:10:29.000000+0000 | 2019-10-30 19:10:29.000000+0000 |      True | This is an alert1 | 8b13db5c-9e39-4ee5-90a9-64758c5ab5be | alert1

(3 rows)

而且它不能工作,因为Cassandra被设计成按顺序从磁盘读写数据。允许在一个查询中对多个列进行范围查询需要Cassandra进行随机读取,这是Cassandra所不擅长的。您可以使用
ALLOW FILTERING
指令来实现这一点,但不建议这样做。尽管如此,在小分区内使用
ALLOW FILTERING
可能会正常运行。

在您的示例中,只需对month_bucket进行一个小注释:即使每个月只有几千个条目,这也会导致大分区。好吧,很多年后,但只是为了理解:总共只有12个分区entries@AlexTbk该年也是2019年10月
月的一部分,例如:
201910
;因此,2020年10月(
202010
)将是一个不同的桶(分区)。正如我所指出的,选择月份只是为了演示。可以使用更精确的时间段,同时交易一些查询灵活性。
AND start_date_time >= '2019-10-30 14:10:29'  AND end_date_time <= '2019-10-31 23:59:59';