Cassandra:列出最近修改的10条记录

Sha*_*aun 11 cql cassandra

我在尝试对数据进行建模时遇到了麻烦,以至于我可以有效地查询Cassandra最近修改的最后10个(实际上是任何数量)记录.每个记录都有一个last_modified_date列,由应用程序在插入/更新记录时设置.

我已从此示例代码中排除了数据列.

主数据表(每条记录只包含一行):

CREATE TABLE record (
    record_id int,
    last_modified_by text,
    last_modified_date timestamp,
    PRIMARY KEY (record_id)
);
Run Code Online (Sandbox Code Playgroud)

解决方案1(失败)

我试图创建一个单独的表,它使用了一个聚类键顺序.

表(每条记录一行;仅插入最后修改日期):

CREATE TABLE record_by_last_modified_index (
    record_id int,
    last_modified_by text,
    last_modified_date timestamp,
    PRIMARY KEY (record_id, last_modified_date)
) WITH CLUSTERING ORDER BY (last_modified_date DESC);
Run Code Online (Sandbox Code Playgroud)

查询:

SELECT * FROM record_by_last_modified_index LIMIT 10
Run Code Online (Sandbox Code Playgroud)

此解决方案不起作用,因为群集顺序仅适用于具有相同分区键的记录的排序.由于每行具有不同的分区键(record_id),因此查询结果不包括预期记录.

解决方案2(效率低下)

我尝试的另一个解决方案是简单地查询Cassandra的所有record_id和last_modified_date值,对它们进行排序并选择我的应用程序中的前10条记录.这显然效率低下,并且不能很好地扩展.

解决方案3

我考虑的最后一个解决方案是对所有记录使用相同的分区键,并使用聚类顺序确保记录正确排序.该解决方案的问题在于,数据将无法在节点之间正确分区,因为所有记录都具有相同的分区键.这对我来说似乎不是一件好事.

Jim*_*yer 16

我认为你要做的更多的是关系数据库模型,而且在Cassandra中有点反模式.

Cassandra只根据聚类列对事物进行排序,但排序顺序不会发生变化.这是因为当memtables作为SSTables(Sorted String Tables)写入磁盘时,SSTable是不可变的,无法有效地重新排序.这就是不允许您更新群集列的值的原因.

如果要对群集行重新排序,我知道的唯一方法是删除旧行并在批处理中插入新行.为了使效率更低,您可能需要首先读取以找出last_modified_date对于record_id的内容,以便您可以删除它.

所以我会寻找一种不同的方法,例如将更新写为新的聚簇行并将旧的那些留在那里(可能使用TTL随时间清理它们).因此,当您执行LIMIT查询时,您的最新更新将始终位于顶部.

在分区方面,您需要将数据分成几个类别,以便在节点上传播数据.这意味着您不会对表进行全局排序,而只是在类别中,这是由分布式模型引起的.如果你真的需要全局排序,那么或许看看像Cassandra和Spark一样的东西.排序在时间和资源上非常昂贵,因此请仔细考虑是否真的需要它.

更新:

考虑到这一点,您应该能够使用物化视图在Cassandra 3.0中执行此操作.该视图将处理杂乱删除并为您插入,以重新排序群集行.所以这是3.0 alpha版本中的样子:

首先创建基表:

CREATE TABLE record_ids (
    record_type int,
    last_modified_date timestamp,
    record_id int,
    PRIMARY KEY(record_type, record_id));
Run Code Online (Sandbox Code Playgroud)

然后使用last_modified_date作为聚类列创建该表的视图:

CREATE MATERIALIZED VIEW last_modified AS
    SELECT record_type FROM record_ids
    WHERE record_type IS NOT NULL AND last_modified_date IS NOT NULL AND record_id IS NOT NULL
    PRIMARY KEY (record_type, last_modified_date, record_id)
    WITH CLUSTERING ORDER BY (last_modified_date DESC);
Run Code Online (Sandbox Code Playgroud)

现在插入一些记录:

insert into record_ids (record_type, last_modified_date, record_id) VALUES ( 1, dateof(now()), 100);
insert into record_ids (record_type, last_modified_date, record_id) VALUES ( 1, dateof(now()), 200);
insert into record_ids (record_type, last_modified_date, record_id) VALUES ( 1, dateof(now()), 300);

SELECT * FROM record_ids;

 record_type | record_id | last_modified_date
-------------+-----------+--------------------------
           1 |       100 | 2015-08-14 19:41:10+0000
           1 |       200 | 2015-08-14 19:41:25+0000
           1 |       300 | 2015-08-14 19:41:41+0000

SELECT * FROM last_modified;

 record_type | last_modified_date       | record_id
-------------+--------------------------+-----------
           1 | 2015-08-14 19:41:41+0000 |       300
           1 | 2015-08-14 19:41:25+0000 |       200
           1 | 2015-08-14 19:41:10+0000 |       100
Run Code Online (Sandbox Code Playgroud)

现在我们更新基表中的记录,并且应该看到它移动到视图中列表的顶部:

UPDATE record_ids SET last_modified_date = dateof(now()) 
WHERE record_type=1 AND record_id=200;
Run Code Online (Sandbox Code Playgroud)

所以在基表中,我们看到record_id = 200的时间戳已更新:

SELECT * FROM record_ids;

 record_type | record_id | last_modified_date
-------------+-----------+--------------------------
           1 |       100 | 2015-08-14 19:41:10+0000
           1 |       200 | 2015-08-14 19:43:13+0000
           1 |       300 | 2015-08-14 19:41:41+0000
Run Code Online (Sandbox Code Playgroud)

在视图中,我们看到:

 SELECT * FROM last_modified;

 record_type | last_modified_date       | record_id
-------------+--------------------------+-----------
           1 | 2015-08-14 19:43:13+0000 |       200
           1 | 2015-08-14 19:41:41+0000 |       300
           1 | 2015-08-14 19:41:10+0000 |       100
Run Code Online (Sandbox Code Playgroud)

因此,您会看到record_id = 200在视图中向上移动,如果您在该表上执行了N限制,则会获得N个最近修改过的行.

  • 你肯定在这里获得了+1! (4认同)
  • 我一定会考虑使用物化视图.在Cassandra 3.0稳定之前,我不能使用它.这个问题最困难的部分是找出合适的分区键.这些记录没有"record_type"列并且相当稀疏,因此我唯一的解决方案可能是生成任意分区键,该键仅用于对数据进行分区.谢谢! (2认同)