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

标签 cassandra cql

我在尝试为我的数据建模时遇到了问题,以便我可以有效地查询 Cassandra 以获取最近修改的最后 10 条(实际上是任意数字)记录。每条记录都有一个 last_modified_date 列,由应用程序在插入/更新记录时设置。

我已经从这个示例代码中排除了数据列。

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

CREATE TABLE record (
    record_id int,
    last_modified_by text,
    last_modified_date timestamp,
    PRIMARY KEY (record_id)
);

解决方案 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);

查询:
SELECT * FROM record_by_last_modified_index LIMIT 10

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

解决方案2(低效)

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

解决方案3

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

最佳答案

我认为您想要做的更多是关系数据库模型,并且在 Cassandra 中有点反模式。

Cassandra 仅根据聚类列对事物进行排序,但预计排序顺序不会改变。这是因为当 memtables 作为 SSTables(Sorted String Tables)写入磁盘时,SSTables 是不可变的,不能有效地重新排序。这就是为什么不允许更新聚集列的值的原因。

如果要对聚集的行重新排序,我知道的唯一方法是删除旧行并批量插入新行。为了使其效率更低,您可能需要先读取以找出 record_id 的 last_modified_date 是什么,以便您可以删除它。

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

在分区方面,您需要将数据分成几个类别,以将数据分布在您的节点上。这意味着您不会对表进行全局排序,而只能在类别内进行排序,这是由于分布式模型所致。如果您真的需要全局排序,那么也许可以看看将 Cassandra 与 Spark 配对之类的东西。排序在时间和资源上是非常昂贵的,所以如果你真的需要它,请仔细考虑。

更新:

再考虑一下,您应该能够在 Cassandra 3.0 中使用物化 View 来做到这一点。该 View 将为您处理困惑的删除和插入,以重新排序聚集的行。所以这是 3.0 alpha 版本中的样子:

首先创建基表:

CREATE TABLE record_ids (
    record_type int,
    last_modified_date timestamp,
    record_id int,
    PRIMARY KEY(record_type, record_id));

然后创建该表的 View ,使用 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);

现在插入一些记录:
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

现在我们更新基表中的一条记录,应该会看到它移动到 View 中列表的顶部:
UPDATE record_ids SET last_modified_date = dateof(now()) 
WHERE record_type=1 AND record_id=200;

因此,在基表中,我们看到 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

在 View 中,我们看到:
 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

因此,您会看到 record_id=200 在 View 中向上移动,如果您对该表进行限制 N,您将获得 N 个最近修改的行。

关于Cassandra:列出最近修改的 10 条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32014367/

相关文章:

java - 如何在 cassandra 中创建键空间?

Cassandra 子查询备用

python - 使用cql从python插入到cassandra

cassandra - 使用 timeuuid CQL 的聚类顺序

c# - 节俭.Transport.TTransportException : Cannot write to null outputstream

python - Shared Cassandra Session 失去连接,应用必须重启

cassandra - 在哪里可以找到 Titan 错误日志?

cassandra - Spring 数据 : Connect to Cassandra via SSL

docker - 如何在 cassandra 的 docker 实例中启用用户定义的函数?

cassandra - 为什么我们在 cassandra 中需要二级索引,它们是如何工作的?