我从过去几天开始学习cassandra。试图为以下用例创建数据模型..
"Each Zipcode in US has a list of stores sorted based on a defined rank"
"Each store/warehouse has millions of SKUs and the inventory is tracked"
"If I search using a zipcode and SKU, it should return the best possible 100 stores
with inventory, based on the rank"
Assume store count is 1000+ and sku count is in millions
设计尝试
One table with
ZipCode
Rank
StoreID
primary key (ZipCode, Rank)
Another table with
Sku
Store
Inventory
Primary Key (Sku, Store)
现在,如果我想为每个ZipCode,SKU搜索前100个商店 组合..
我必须在表1中搜索前100家商店和 然后从第二张表中提取每个商店的库存。
由于SKU计数是以百万计,而存储计数是1000+,所以不是 确定我们是否可以将所有这些存储在一个表中并将zipcode_sku作为行 密钥,商店和库存存储为按行排序的宽行
我在想吗?这个用例的其他可能的数据模型是什么?
更新:数据加载器代码(如下面的评论所述)
println "Loading data started.."
(1..1000000).each { // SKUs
sku = it.toString()
(1..42000).each { // Zip Codes
zipcode = it.toString().padLeft(5,"0")
(1..1500).each { // Stores
store = it.toString()
int inventory = Math.abs(new Random().nextInt() % 10000) + 1
session.execute("INSERT INTO ritz.rankedStoreByZipcodeAndSku(sku, zipcode, store, store_rank, inventory) " +
"VALUES('$sku','$zipcode','$store',$it,$inventory);")
}
}
}
println "Data Loaded"
答案 0 :(得分:1)
Cassandra是一个Columnar数据库,因此您可以拥有通常希望表示要进行的每种查询的宽行。在这种情况下
CREATE TABLE storeByZipcodeAndSku (
sku text,
zipcode int,
store text,
store_rank int,
inventory int,
PRIMARY KEY ((sku, zipcode), store)
);
这样行键是sku + zipcode,所以它的查找非常快,你可以存储多达20亿个商店。更新库存时,也请更新此表。要获得前100名,你只需要下拉所有这些并排序(1000' s并不多)但是如果这个操作非常普遍而你需要它更快,你可以改为使用
CREATE TABLE rankedStoreByZipcodeAndSku (
...
PRIMARY KEY ((sku, zipcode), store_rank)
) WITH CLUSTERING ORDER BY (store_rank ASC);
让它自动为你排序,你只需要获得前100名。然后当你更新它时,你会希望使用轻量级事务以原子方式移动。
答案 1 :(得分:0)
听起来您想要从第一个表格中获取基于ZipCode的StoreID列表,以及基于Sku从第二个表格中获取StoreID列表,然后进行连接。由于Cassandra是一个简单的键值存储,它不会加入。因此,您必须在客户端编写代码来执行两个查询并手动执行连接,或者将Cassandra连接到具有连接函数的spark。
正如您所说,尝试将两个表反规范化为一个表,以便您可以在一个查询中执行此操作,这可能会导致一个非常大且难以维护的表。如果这是您将拥有的唯一查询模式,那么这可能是值得的,但如果这是一个具有许多不同查询模式的一般库存系统,那么它可能太不灵活了。
另一个选择是使用RDBMS而不是Cassandra,然后加入非常容易。