Cassandra:只选择最新的行


Cassandra: select only latest rows

我使用下表:

CREATE TABLE IF NOT EXISTS lp_registry.domain (
    ownerid text,
    name1st text,
    name2nd text,
    name3rd text,
    registrar text,
    registered timestamp,
    expiration timestamp,
    updated timestamp,
    technologies list<text>,
    techversions list<text>,
    ssl boolean,
    PRIMARY KEY (
        (name1st, name2nd, name3rd), 
        registrar, ownerid, registered, expiration, updated
    )
);

表不会更新,只会添加新行。每次爬网程序检查域时,都会添加新行。

我正在执行此选择:

SELECT * FROM lp_registry.domain WHERE 
    registrar = 'REG-WEDOS' AND 
    ownerid = 'FORPSI-JAF-S497436' 
ALLOW FILTERING;

但我想要的结果只是每个唯一的"name3rd.name2nd.name1st"具有最新"更新"值的行。

如果我在标准SQL数据库中,我会使用带有MAX或GROUP BY的嵌套select。但是,Cassandra不支持这一点(在Cassandra中为MAX()、DISTINCT和GROUP BY)。但我在CQL应该做什么?

扩展到Cedric的答案(这是一个很好的建议,并将其视为可接受的答案),您将获得大致如下的表结构:

CREATE TABLE IF NOT EXISTS lp_registry.domain (
    ownerid text,
    name1st text,
    name2nd text,
    name3rd text,
    registrar text,
    registered timestamp,
    expiration timestamp,
    updated timestamp,
    technologies list<text>,
    techversions list<text>,
    ssl boolean,
    PRIMARY KEY ((registrar, ownerid), updated, name1st, name2nd, name3rd)
) WITH CLUSTERING ORDER BY (updated desc);

当选择数据时,它将返回分区中具有最新updated值的行,用于您正在查询的注册器和所有者。

这个查询将非常快,因为您的数据将按注册商、所有者id和行(按更新降序排列)在磁盘上进行组织。

这是cassandra的一个关键概念,因为你的数据是根据你的查询方式来组织的。你在查询中失去了灵活性,但你可以放心,你会得到很好的性能,因为你是按照组织的方式检索数据的。这就是为什么基于查询取消规范化数据至关重要的原因。

如果您想检索所有数据的最新更新,情况就会变得复杂。使用cassandra不容易解决这个问题,除非所有东西都共享同一个分区,该分区有自己的一组问题(例如使用"伪"分区键的策略)。

应该修改整个架构。从应用程序的角度来看,您正在执行的SELECT显然是一个重要的任务,不应该需要ALLOW FILTERING:您应该取消数据的规范化,并创建一个表,其中registrarownerid是分区键。

在这个非规范化结构中,updated应该是一个分区键,用DESC排序。然后查询将是

SELECT * FROM lp_registry.domain WHERE registrar='XXX' AND ownerid='YYY' LIMIT 10;

正如您所说的,行被插入但从未更新,在您的应用程序中,如果必要的话,在多个非规范化表中插入新数据应该不会很复杂。

Andy的回答为您的表格结构提供了更多细节和示例。