Cassandra表行唯一性需求:PRIMARY KEY(hash,created)需仅hash唯一
解决方案
要实现hash字段唯一且支持按created降序查询的需求,需要调整表的主键设计,并配合物化视图来实现排序功能,具体步骤如下:
1. 修改主表结构,保证hash唯一性
将hash设为唯一的分区键(主键),这样Cassandra会强制每个hash值仅对应一行数据,满足唯一性要求。同时可以给created列设置默认值,自动记录行的创建时间:
CREATE TABLE IF NOT EXISTS keyspace.table ( account varchar, hash varchar, lt bigint, created timestamp DEFAULT toTimestamp(now()), PRIMARY KEY (hash) );
说明:
- 分区键
hash直接保证了唯一性,同一hash无法插入多行数据。 DEFAULT toTimestamp(now())会自动将created设为当前时间,无需手动插入时指定。
2. 创建物化视图实现按created降序排序
Cassandra本身不支持全局跨分区排序(直接查询主表用ORDER BY created DESC会在客户端拉取全量数据排序,性能极差),因此需要创建物化视图,将created作为排序依据:
CREATE MATERIALIZED VIEW IF NOT EXISTS keyspace.table_by_created AS SELECT account, hash, lt, created FROM keyspace.table WHERE hash IS NOT NULL AND created IS NOT NULL PRIMARY KEY (created, hash) WITH CLUSTERING ORDER BY (created DESC);
说明:
- 物化视图的主键设计为
(created, hash),其中created是分区键,hash是聚类键:- 按
created分区可以让相同时间范围的数据存储在一起,提升排序查询的性能。 - 加入
hash作为聚类键,避免同一created值下出现重复数据(因为主表hash唯一,物化视图中每个hash也只会存在一行)。
- 按
WITH CLUSTERING ORDER BY (created DESC)指定了在同一分区内按created降序排列,全局查询时就能直接得到按时间降序的结果。
3. 查询方式
- 要查询唯一
hash对应的行,直接查询主表:SELECT * FROM keyspace.table WHERE hash = 'xxx'; - 要按
created降序查询所有数据,查询物化视图:SELECT * FROM keyspace.table_by_created;
为什么原建表语句不满足需求?
原语句中PRIMARY KEY (hash, created)是复合主键,其中hash是分区键,created是聚类键:
- 唯一性由
hash + created的组合决定,因此同一hash可以插入多个不同created值的行,不符合你要求的hash唯一的规则。 - 聚类键的排序仅作用于同一
hash分区内的行,无法实现全局按created降序的效果。
内容的提问来源于stack exchange,提问作者Shayan Shojaei
相关产品推荐
相关产品推荐

