如何将元素添加到具有与 Cassandra 中其他列相同的 TTL 的集合中
How to add an element to a collection with the same TTL of other column in Cassandra
我有一个Table
CREATE TABLE myTable (
id bigint,
other_id text,
my_set SET<bigint>,
my_date timestamp,
PRIMARY KEY (id, other_id)
);
我想在所有列中有一个共同的 TTL,因此在 TTL 过期后,该行消失。
我设法插入新行:
INSERT INTO myTable (id, other_id, my_date, my_set)
VALUES (1,'foo','2014-10-20 12:05:08-0300', {22})
USING TTL 20;
我还可以更新我的集合,添加新元素:
UPDATE myTable USING TTL 20 SET my_set=my_set + {99}
WHERE id=1 AND other_id='foo';
但我的问题是这个新元素有一个新的 TTL,所以一段时间后数字 22 消失了,而 99 仍然存在。
如何向我的集合中添加一个与集合中其他元素具有相同 TTL 的新元素?
我想到的解决办法是做两个查询:
- 询问my_date列他的TTL
- 使用该 TTL 进行更新,将新元素添加到 my_set
有更好的解决办法吗?
您可以在 SELECT
中使用 TTL()
函数
SELECT TTL(my_set) FROM myTable;
然后使用该值...但我认为这对您尝试做的事情不起作用。
相反,我会添加创建该行的日期。或多或少,是这样的:
CREATE TABLE myTable (..., created_on timestamp);
INSERT INTO myTable (..., created_on) VALUES (..., toTimestamp(now()));
...
SELECT created_on FROM myTable WHERE ...
INSERT INTO myTable ... USING TTL now - created_on ...
(而不是 toTimestamp(now())
,您可能必须使用 dateOf(now())
,具体取决于您使用的 CQL 版本;see documentation。当然,您也可以使用自己的时间戳值.)
如果 now - created_on
小于 1,则不应处理该 INSERT。 (实际上,我在某处读到 TTL 的最小值可能至少应为 3 秒,但对于数据库 TTL 来说,即使是 3 秒也确实很小...)
还有一个writetime()
功能。但我不太确定这是否适合你。你当然可以试试看:
SELECT writetime(id) FROM myTable WHERE ...
writetime()
在更新时发生变化的可能性不大,但我不知道它是按列还是按行变化,不建议将此类系统信息用于您自己的数据(How to retrieve the timestamp from cassandra?).
我不太了解您的解决方案试图实现的目标。但是根据我的经验,大型集合中的 TTL 是个坏消息(或者在一个集合中有超过几十个元素)。
无论如何,因为在幕后,集合是以 (name=setName:valueOfItem, value=) (see this article for more) 形式作为离散列实现的,因此您必须在顶部进行一些修改。我的建议是将您的 Collection 封装在一个集群列中,如下所示:
CREATE TABLE my_table (
id bigint,
other_id text,
collection_ttl timeuuid,
my_set SET<bigint>,
my_date timestamp,
PRIMARY KEY (id, other_id, collection_ttl)
);
其中 collection_ttl 可能只是插入时间,本质上是为了跟踪包含的集合的 TTL。
或者您可以将您的 Set 展开到 Clustering 列中,并通过执行以下操作实现基本相同的效果:
CREATE TABLE my_table_no_set (
id bigint,
other_id text,
my_set_key bigint,
my_set_value text,
my_date timestamp,
PRIMARY KEY (id, other_id, my_set_value)
);
如果你有一个相当大的集合,这对 Cassandra 会更友好,你可以在 order_id 或类似的东西上做一个 TTL。
我有一个Table
CREATE TABLE myTable (
id bigint,
other_id text,
my_set SET<bigint>,
my_date timestamp,
PRIMARY KEY (id, other_id)
);
我想在所有列中有一个共同的 TTL,因此在 TTL 过期后,该行消失。
我设法插入新行:
INSERT INTO myTable (id, other_id, my_date, my_set)
VALUES (1,'foo','2014-10-20 12:05:08-0300', {22})
USING TTL 20;
我还可以更新我的集合,添加新元素:
UPDATE myTable USING TTL 20 SET my_set=my_set + {99}
WHERE id=1 AND other_id='foo';
但我的问题是这个新元素有一个新的 TTL,所以一段时间后数字 22 消失了,而 99 仍然存在。
如何向我的集合中添加一个与集合中其他元素具有相同 TTL 的新元素?
我想到的解决办法是做两个查询:
- 询问my_date列他的TTL
- 使用该 TTL 进行更新,将新元素添加到 my_set
有更好的解决办法吗?
您可以在 SELECT
TTL()
函数
SELECT TTL(my_set) FROM myTable;
然后使用该值...但我认为这对您尝试做的事情不起作用。
相反,我会添加创建该行的日期。或多或少,是这样的:
CREATE TABLE myTable (..., created_on timestamp);
INSERT INTO myTable (..., created_on) VALUES (..., toTimestamp(now()));
...
SELECT created_on FROM myTable WHERE ...
INSERT INTO myTable ... USING TTL now - created_on ...
(而不是 toTimestamp(now())
,您可能必须使用 dateOf(now())
,具体取决于您使用的 CQL 版本;see documentation。当然,您也可以使用自己的时间戳值.)
如果 now - created_on
小于 1,则不应处理该 INSERT。 (实际上,我在某处读到 TTL 的最小值可能至少应为 3 秒,但对于数据库 TTL 来说,即使是 3 秒也确实很小...)
还有一个writetime()
功能。但我不太确定这是否适合你。你当然可以试试看:
SELECT writetime(id) FROM myTable WHERE ...
writetime()
在更新时发生变化的可能性不大,但我不知道它是按列还是按行变化,不建议将此类系统信息用于您自己的数据(How to retrieve the timestamp from cassandra?).
我不太了解您的解决方案试图实现的目标。但是根据我的经验,大型集合中的 TTL 是个坏消息(或者在一个集合中有超过几十个元素)。
无论如何,因为在幕后,集合是以 (name=setName:valueOfItem, value=) (see this article for more) 形式作为离散列实现的,因此您必须在顶部进行一些修改。我的建议是将您的 Collection 封装在一个集群列中,如下所示:
CREATE TABLE my_table (
id bigint,
other_id text,
collection_ttl timeuuid,
my_set SET<bigint>,
my_date timestamp,
PRIMARY KEY (id, other_id, collection_ttl)
);
其中 collection_ttl 可能只是插入时间,本质上是为了跟踪包含的集合的 TTL。
或者您可以将您的 Set 展开到 Clustering 列中,并通过执行以下操作实现基本相同的效果:
CREATE TABLE my_table_no_set (
id bigint,
other_id text,
my_set_key bigint,
my_set_value text,
my_date timestamp,
PRIMARY KEY (id, other_id, my_set_value)
);
如果你有一个相当大的集合,这对 Cassandra 会更友好,你可以在 order_id 或类似的东西上做一个 TTL。