在阅读DataStax blog时,我正在测试切片查询,即使博客已经用Cassandra2完成了,而我们已经使用了3。
因此,我将测试表定义为bellow。
CREATE TABLE foo(
part_key TEXT,
start_ts INT,
end_ts INT,
PRIMARY KEY(part_key, start_ts, end_ts)
) WITH CLUSTERING ORDER BY (start_ts ASC, end_ts ASC);
此表中插入了某些装置。
INSERT INTO foo(part_key, start_ts, end_ts) VALUES ('A', 1, 5);
INSERT INTO foo(part_key, start_ts, end_ts) VALUES ('A', 2, 3);
INSERT INTO foo(part_key, start_ts, end_ts) VALUES ('B', 4, 7);
INSERT INTO foo(part_key, start_ts, end_ts) VALUES ('B', 9, 13);
INSERT INTO foo(part_key, start_ts, end_ts) VALUES ('B', 1, 2);
INSERT INTO foo(part_key, start_ts, end_ts)
VALUES ('B', 9, 9999); -- 9999 = symbolic value for no end
我首先检查B
分区:
> SELECT * FROM foo WHERE part_key='B';
part_key | start_ts | end_ts
----------+----------+--------
B | 1 | 2
B | 4 | 7
B | 9 | 13
B | 9 | 9999
(4 rows)
我们不能执行“自然”查询SELECT * FROM foo WHERE part_key='B' AND start_ts <= 7 AND end_ts >= 7
,因为它会引发以下错误。
InvalidRequest: Error from server: code=2200 [Invalid query] message="Clustering column "end_ts" cannot be restricted (preceding column "start_ts" is restricted by a non-EQ relation)"
在DataStax博客中,有一个查询如下。
SELECT * FROM numberOfRequests
WHERE cluster = ‘cluster1’
AND date = ‘2015-06-05’
AND datacenter = 'US_WEST_COAST'
AND (hour, minute) >= (12, 30) AND (hour) < (14)
因此,我们尝试使用以下切片查询解决此问题,始终使用start_ts >= -9999
,并允许一起为end_ts
指定不等式条件。
SELECT * FROM foo WHERE part_key='B'
AND (start_ts, end_ts) >= (-9999, 7) AND start_ts <= 7; -- -9999 = min_value
它在没有任何警告的情况下执行,并给出了如下结果。
part_key | start_ts | end_ts
----------+----------+--------
B | 1 | 2
B | 4 | 7
(2 rows)
此时,第1行(带有start_ts = 1
)对我来说应该不存在,因为end_ts >= 7
对此行不是真的。由于start_ts >= -9999
始终为真,因此似乎忽略了第一个条件(start_ts, end_ts) >= (-9999, 7)
:结果与查询SELECT * FROM foo WHERE part_key='B' AND start_ts <= 7
相同。
读到博客的例子,我在想(至少在c2.2中),(start_ts, end_ts) >= (-9999, 7) AND start_ts <= 7
的意思是start_ts >= -9999 AND end_ts >= 7 AND start_ts <= 7
,类似于(start_ts, end_ts) = (4, 7)
,意思是start_ts = 4 AND end_ts = 7
。
SELECT * FROM foo WHERE part_key='B' AND (start_ts, end_ts) = (4, 7);
part_key | start_ts | end_ts
----------+----------+--------
B | 4 | 7
(1 rows)
这种类似元组的不平等到底是如何解释的?有没有办法更新它,让它“工作”?
发布于 2017-08-12 02:06:15
让我们再插入一些记录
INSERT INTO foo (part_key, start_ts , end_ts ) VALUES ( 'B', 1, 7);
INSERT INTO foo (part_key, start_ts , end_ts ) VALUES ( 'B', 4, 8);
INSERT INTO foo (part_key, start_ts , end_ts ) VALUES ( 'B', 9, 7);
现在我们有了part_key = 'B‘的数据
cqlsh:test> SELECT * FROM foo WHERE part_key='B' ;
part_key | start_ts | end_ts
----------+----------+--------
B | 1 | 2
B | 1 | 7
B | 4 | 7
B | 4 | 8
B | 9 | 7
B | 9 | 13
B | 9 | 9999
现在让我们对此数据进行查询:
cqlsh:test> SELECT * FROM foo WHERE part_key='B' AND (start_ts, end_ts) >= (1, 4) AND (start_ts, end_ts) <= (9, 7);
part_key | start_ts | end_ts
----------+----------+--------
B | 1 | 7
B | 4 | 7
B | 4 | 8
B | 9 | 7
似乎结果是不正确的。但事实并非如此。我们的理解是错误的。
Cassandra将存储按复合字段( start_ts,end_ts)排序的数据,首先按start_ts排序,然后按每个start_ts排序end_ts排序。当我们使用(start_ts, end_ts) >= (1, 4) AND (start_ts, end_ts) <= (9, 7)
进行查询时。Cassandra将(start_ts, end_ts)
视为单个复合字段,其取值范围在(1,4)到(9,7)之间
part_key | start_ts | end_ts
----------+----------+--------
B | 1 | 2
-------------------------------> start range
B | 1 | 7
B | 4 | 7
B | 4 | 8
B | 9 | 7
-------------------------------> end range
B | 9 | 13
B | 9 | 9999
希望你能理解。
发布于 2017-08-12 02:40:09
这里的比较是按元组进行的-因为您已经将两列合并到一个元组中,所以您得到的比较行为与预期略有不同。这是正确的,只是不是你所期望的。
(start_ts, end_ts) >= (-9999, 7)
这并不意味着start_ts >= -9999 && end_ts >= 7
,它意味着左(包括)界是元组(-9999,7)
。可能存在大于(-9999,7)
的元组(-9998,1)
,即使end_ts==1
小于7
发布于 2017-08-29 15:51:00
一种可能的方法是对第二列使用过滤。不幸的是,仅在3.6版本之后才支持对聚类列进行过滤。因此,如果您的版本比这个版本小,但是是3.0.x版本,那么您可以通过将第二个聚集列转换为常规的聚集列来解决问题。在这种情况下,下面的查询将为您提供预期的结果:
SELECT * FROM foo WHERE part_key='B' AND start_ts = 7 ALLOW FILTERING
现在,我不知道你的数据和它的基数,所以过滤可能不是一个好的选择。
另一种选择是更改您的数据模型。有不同的方法可以对事物进行建模,以便以有效的方式获得满足您需求的查询。
https://stackoverflow.com/questions/45639668
复制相似问题