首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Cassandra切片查询非常奇怪的结果

Cassandra切片查询非常奇怪的结果
EN

Stack Overflow用户
提问于 2017-08-12 00:21:42
回答 4查看 438关注 0票数 1

在阅读DataStax blog时,我正在测试切片查询,即使博客已经用Cassandra2完成了,而我们已经使用了3。

因此,我将测试表定义为bellow。

代码语言:javascript
运行
复制
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);

此表中插入了某些装置。

代码语言:javascript
运行
复制
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分区:

代码语言:javascript
运行
复制
> 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,因为它会引发以下错误。

代码语言:javascript
运行
复制
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博客中,有一个查询如下。

代码语言:javascript
运行
复制
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指定不等式条件。

代码语言:javascript
运行
复制
SELECT * FROM foo WHERE part_key='B'
AND (start_ts, end_ts) >= (-9999, 7) AND start_ts <= 7; -- -9999 = min_value

它在没有任何警告的情况下执行,并给出了如下结果。

代码语言:javascript
运行
复制
 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

代码语言:javascript
运行
复制
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)

这种类似元组的不平等到底是如何解释的?有没有办法更新它,让它“工作”?

EN

回答 4

Stack Overflow用户

发布于 2017-08-12 02:06:15

让我们再插入一些记录

代码语言:javascript
运行
复制
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‘的数据

代码语言:javascript
运行
复制
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

现在让我们对此数据进行查询:

代码语言:javascript
运行
复制
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)之间

代码语言:javascript
运行
复制
 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

希望你能理解。

票数 1
EN

Stack Overflow用户

发布于 2017-08-12 02:40:09

这里的比较是按元组进行的-因为您已经将两列合并到一个元组中,所以您得到的比较行为与预期略有不同。这是正确的,只是不是你所期望的。

代码语言:javascript
运行
复制
(start_ts, end_ts) >= (-9999, 7)

这并不意味着start_ts >= -9999 && end_ts >= 7,它意味着左(包括)界是元组(-9999,7)。可能存在大于(-9999,7)的元组(-9998,1),即使end_ts==1小于7

票数 1
EN

Stack Overflow用户

发布于 2017-08-29 15:51:00

一种可能的方法是对第二列使用过滤。不幸的是,仅在3.6版本之后才支持对聚类列进行过滤。因此,如果您的版本比这个版本小,但是是3.0.x版本,那么您可以通过将第二个聚集列转换为常规的聚集列来解决问题。在这种情况下,下面的查询将为您提供预期的结果:

代码语言:javascript
运行
复制
SELECT * FROM foo WHERE part_key='B' AND start_ts = 7 ALLOW FILTERING

现在,我不知道你的数据和它的基数,所以过滤可能不是一个好的选择。

另一种选择是更改您的数据模型。有不同的方法可以对事物进行建模,以便以有效的方式获得满足您需求的查询。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45639668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档