【问题标题】:CAS with CQL in Cassandra在 Cassandra 中使用 CQL 的 CAS
【发布时间】:2017-02-23 08:32:31
【问题描述】:

我正在尝试在 Cassandra 中对一些时间序列数据进行建模,我可以使用旧的 thrift 客户端进行建模,但 CQL 似乎让我失望了。

如果特定列值匹配,我想在我的行中添加一个新列。

我的表定义是:

CREATE TABLE TestTable (
   key int,
   base uuid,
   ts int,                   // Timestamp (column name)
   val text,                 // Timestamp value (column value)
   PRIMARY KEY (key, ts)
) WITH CLUSTERING ORDER BY (ts DESC);

我猜它的样子是:

Row | UUID | TS  | TS | TS
--- | ---- | --- | ---| ---
 1  | id1  |  1  |  2 |  3
--- | ---  | --- | ---| ---
 2  | id2  |  1  |  5 |  6

所以本质上,我可以为给定的行设置一堆时间戳,为一行设置一个单一的 UUID。 需要为 TS 列的每个新插入更新 UUID。

所以连续插入就可以了:

insert into TestTable(key, base, ts, val) values (1, dfb63886-91a4-11e6-ae22-56b6b6499611, 50, 'one')

但我想不出一种方法,使用 CQL,使用 Cassandra 事务 (CAS) 在行中插入新列。

这个失败了:

insert into TestTable(key, base, ts, val) values (1, dfb63886-91a4-11e6-ae22-56b6b6499611, 70, 'four') if base = dfb63886-91a4-11e6-ae22-56b6b6499611;

出现错误:

SyntaxException: <ErrorMessage code=2000 [Syntax error in CQL query] message="line 1:106 mismatched input 'base' expecting K_NOT (..., 70, 'four') if [base] =...)">

还有查询:

update TestTable set val = 'four', ts=70  where key = 1 if base = dfb63886-91a4-11e6-ae22-56b6b6499611;

失败并出现错误:

InvalidRequest: code=2200 [Invalid query] message="PRIMARY KEY part ts found in SET part"

我正在尝试弄清楚如何正确地对数据进行建模,以便我每行只有一个 UUID,并且可以有多个列,而不必在表创建期间显式定义它们,因为它可能会有很大差异。

IIRC,使用 thrift 客户端很容易做到这一点,但使用它不是一个选项 =/

【问题讨论】:

    标签: cassandra transactions


    【解决方案1】:

    有一个很好的关于数据系列的教程here

    简而言之,您的复合键将是您的唯一标识符(如您提议的 UUID)和时间戳,因此您将能够添加与 UUID 关联的尽可能多的事件/值

    CREATE TABLE IF NOT EXISTS TestTable (
       base uuid,
       ts timestamp,             // Timestamp (column name)
       value text,                 // Timestamp value (column value)
       PRIMARY KEY (base, ts)
    ) WITH CLUSTERING ORDER BY (ts DESC);
    

    添加值将具有相同的 UUID 不同的时间:

    INSERT INTO TestTable (base, ts, value) 
        VALUES (467286c5-7d13-40c2-92d0-73434ee8970c, dateof(now()), 'abc');
    
    INSERT INTO TestTable (base, ts, value) 
        VALUES (467286c5-7d13-40c2-92d0-73434ee8970c, dateof(now()), 'def');
    
    cqlsh:test> SELECT * FROM TestTable WHERE base = 467286c5-7d13-40c2-92d0-73434ee8970c;
    
     base                                 | ts                              | value
    --------------------------------------+---------------------------------+-------
     467286c5-7d13-40c2-92d0-73434ee8970c | 2016-10-14 04:13:42.779000+0000 |   def
     467286c5-7d13-40c2-92d0-73434ee8970c | 2016-10-14 04:12:50.551000+0000 |   abc
    
    (2 rows)
    

    可以在任何列中进行更新,除了用作键的列,更新语句中显示的错误是由“IF”语句引起的,因为它试图更新@ 987654325@ 是复合键的一部分。

    INSERT INTO TestTable (base, ts, value)
           VALUES (ffb0bb8e-3d67-4203-8c53-046a21992e52, dateof(now()), 'bananas');
    
    SELECT * FROM TestTable WHERE base = ffb0bb8e-3d67-4203-8c53-046a21992e52 AND ts < dateof(now());
    
     base                                 | ts                              | value
    --------------------------------------+---------------------------------+---------
     ffb0bb8e-3d67-4203-8c53-046a21992e52 | 2016-10-14 04:17:26.421000+0000 | apples
    
    (1 rows)
    
    UPDATE TestTable SET value = 'apples' WHERE base = ffb0bb8e-3d67-4203-8c53-046a21992e52;
    
    SELECT * FROM TestTable WHERE base = ffb0bb8e-3d67-4203-8c53-046a21992e52 AND ts < dateof(now());
    
     base                                 | ts                              | value
    --------------------------------------+---------------------------------+---------
     ffb0bb8e-3d67-4203-8c53-046a21992e52 | 2016-10-14 04:17:26.421000+0000 | bananas
    
    (1 rows)
    

    【讨论】:

    • 所以CQL中没有办法添加任意列并使用CAS?
    • 可以,可以给一行添加动态列,解释是here
    • 表的当前设置方式,它确实添加了动态列。
    • 我正在寻找的是一种使用 CAS(事务)添加动态列的方法
    猜你喜欢
    • 2014-11-15
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2015-11-10
    • 2013-03-16
    • 2018-08-16
    • 2015-11-09
    • 1970-01-01
    相关资源
    最近更新 更多