我目前正在进行Cassandra建模,我有数十亿的某种数字代码hnm_code
可以存储,如下所示:
create table hnm (
create_batch_id int, // A creation batch can generate up to 1 million code.
hnm_code text, // Cardinality: billions
product_name text,
primary key (hnm_code)
);
与create_batch_id
相比,hnm_code
的基数相对较小。但是,我想要的是我应该能够使用单个hnm_code
列的值来查询该记录(查询时create_batch_id
未知)。
我应该使用宽行(带簇密钥的CQL),像这样吗?:
create table hnm_with_cluster_key (
create_batch_id int,
hnm_code text,
product_name text,
primary key (create_batch_id, hnm_code)
);
谢谢!如果您能告诉我如何在大量查询中获得良好性能并均匀分布hnm_code,那将是很好的。
答案 0 :(得分:2)
我想要的是我应该能够使用单个hnm_code列的值来查询该记录
在Cassandra中,您应该设计模型以匹配您的查询模式。所以这个案子说明了一切。在hnm_code
上使用分区键的第一个解决方案将实现此目的。
查询时未知的create_batch_id
如果您要将第二个解决方案与PRIMARY KEY (create_batch_id, hnm_code)
一起使用, 需要在查询时知道(并提供)create_batch_id
。
如果您可以告诉我如何在大量此查询中获得良好性能并均匀分布hnm_code,那将是一件好事。
Cassandra行按分区键的散列值分配。因此,该密钥的基数越高,您在群集中的分布就越均匀。此外,Cassandra旨在通过分区键进行查找,因此您的查询应该非常快。
此外,使用第二个表定义,我的查询如下所示:
select * from hnm_with_cluster_key where hnm_code='1234' allow filtering;
使用数十亿的CQL行数,使用ALLOW FILTERING
指令不表现良好。我强烈建议反对。
现在我想也许我只需要这两个表,一个用于通过单个条件
hnm_code = $hnm_code
选择单个hnm_code行,一个用于通过create_batch_id = $batch_id
选择创建批量的hnm_codes,但我很反感这个重复,考虑到数十亿行加倍。
这就是你问题的症结所在。 Cassandra根本不支持允许这种查询灵活性的类型。从单个表设计支持多个查询通常是不可行的。如果您需要create_batch_id
支持查询,那么您将需要两个表。每个模型都不会支持对另一个模型执行良好的查询。
是的,数据重复/冗余可能违反我们在学校教授的关于规范化的所有内容。但Cassandra并不适合使用完全标准化的模型。我去年为Planet Cassandra撰写了一篇文章,讨论了其中的一些权衡:Escaping Disco-Era Data Modeling。
基本上,虽然大规模数据复制不是任何人真正想做的事情,但在设计高性能Cassandra模型时,这可能是必要的权衡。
答案 1 :(得分:0)
Cassandra与另一个SQL不同,它使用第一个主键作为分区键。在我看来,分区键最好不是唯一的。所以第二种设计更好。