我们使用 Cassandra 的用例是显示博客文章的前 10 位最近访问者。以下是 Cassandra 表定义
CREATE TABLE blogs_by_visitor (
blogposturl text,
visitor text,
visited_ts timestamp,
PRIMARY KEY (blogposturl, visitor)
);
现在,为了显示给定博客文章的前 10 位最近访问者,需要在时间戳记上有一个明确的“order by”子句。由于 visted_ts 不是 Cassandra 中聚类列的一部分,因此我们无法完成此操作。 Visited_ts 不属于聚类列的原因是为了避免记录重复(读为重复)访问者。主键的设计方式是为重复访问者更新插入最新时间戳。
在 RDBMS 世界中,查询如下所示,并且可以使用 blogposturl 和时间戳列创建二级索引。
Select visitor from blog_table
where
blogposturl = ?
and rownum <= 10
order by timestamp desc
我们的 Cassandra 应用程序当前采用的替代方案是获取结果,然后根据应用程序端的时间戳进行排序。但是,如果某个特定的博文变得如此受欢迎并且拥有超过 100,000 名访问者,该怎么办?对于这些博客来说,查询变得非常慢。
我认为二级索引在这里没有用,因为我不担心对其进行过滤(而只是用于排序 - 这是不可能的)。
知道如何以不同的方式对表格进行建模吗?
实际的表格有额外的列,为了简单起见,在此处减少了它
最佳答案
这些类型的工作由 Apache Spark 或 Hadoop 完成。一个调度作业,根据每个 URL 的时间戳计算唯一访问者顺序并将结果存储到 cassandra 中。
或者您可以创建 Materialized View在 blogs_by_visitor
顶部。该表将确保唯一访问者,物化 View 将根据 visited_ts
时间戳对结果进行排序。
让我们创建物化 View :
CREATE MATERIALIZED VIEW unique_visitor AS
SELECT *
FROM blogs_by_visitor
WHERE blogposturl IS NOT NULL AND visitor IS NOT NULL AND visited_ts IS NOT NULL
PRIMARY KEY (blogposturl, visited_ts, visitor)
WITH CLUSTERING ORDER BY (visited_ts DESC, visitor ASC);
现在您只需选择博文的最近 10 位唯一访问者即可。
SELECT * FROM unique_visitor WHERE blogposturl = ? LIMIT 10;
你可以看到我没有在选择查询中指定排序顺序。因为在物化 View 模式中指定了默认排序顺序 visited_ts DESC
请注意:上述架构将导致物化 View 中生成大量意外的逻辑删除
或者您可以更改您的表schmea,如下所示:
CREATE TABLE blogs_by_visitor (
blogposturl text,
year int,
month int,
day int,
visitor text,
visited_ts timestamp,
PRIMARY KEY ((blogposturl, year, month, day), visitor)
);
现在单个分区中只有少量数据。因此您可以从客户端根据该单个分区中的 visited_ts
对所有访问者进行排序。如果您认为一天的访问者数量可能很大,那么还要在分区键中添加小时。
关于Cassandra 按非聚集键对结果进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44212267/