cassandra和< =,=>运算符在日期上不允许过滤

zyfwsgd6  于 2021-06-10  发布在  Cassandra
关注(0)|答案(1)|浏览(394)

我对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;

我不能用 ALLOW FILTERING 我怎么能在Cassandra做这样的查询?

vlf7wbxs

vlf7wbxs1#

我不明白为什么我不能按日期过滤(想返回日期之间的结果)
你看到的行为是因为:

PRIMARY KEY((start_date_time, end_date_time))

你已经定义了 start_date_time 以及 end_date_time 作为复合分区密钥。由于cassandra使用分布式散列来确保正确的数据分布,所以分区不是按值的顺序存储的。它们由分区键的哈希令牌值存储。你可以通过使用 token 分区键上的函数:

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”。在这种情况下,假设您每月编写的条目不会超过几千条。也许不是这样,但我会用它来做这个例子。然后我可以在月份分区,然后使用 _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);

这将按的值将所有行存储在一起 month_bucket ,在每个分区中,行将按 start_date_time 以及 end_date_time 按降序排列。现在它起作用了:

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)

但请注意,只能对单个集群键强制执行范围查询,如 start_date_time 上面。这不行:

AND start_date_time >= '2019-10-30 14:10:29'  AND end_date_time <= '2019-10-31 23:59:59';

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

相关问题