我是Cassandra的新手,想要对用户及其车辆进行一对多的映射。一个用户可能有多个车辆。我的用户表将包含用户详细信息,如姓名,姓氏等。车辆表将包含车辆详细信息。
我的选择查询将获取特定用户的所有车辆详细信息。
我应该如何在Cassandra中设计这个?
答案 0 :(得分:5)
您可以在一个表格中轻松对此进行建模:
CREATE TABLE userVehicles (
userid text,
vehicleid text,
name text static,
surname text static,
vehicleMake text,
vehicleModel text,
vehicleYear text,
PRIMARY KEY (userid,vehicleid)
);
通过这种方式,您可以一次性查询单个用户的车辆,并且您的用户数据可以是static
,以便将其存储在分区键级别。只要用户对车辆的基数不是太大(如同用户有1000辆车一样),这应该可以正常工作。
我上面考虑过的案例非常简单。但是,如果我的用户有大约20到30个字段和车辆相同的详细信息怎么办?你还建议有一张桌子并复制所有车辆的用户数据吗?
这取决于。您的用例是否需要全部返回?如果是,那么"是"我仍然会推荐这种方法。从Cassandra中获得最佳查询性能的方法是对表进行建模以适合您的查询。当Cassandra可以通过特定键或一系列行(按顺序存储)读取单行时效果最佳。您希望避免执行多个查询或编写强制Cassandra执行随机读取的查询。
拥有2个不同的表(如User和Vehicle和Vehicle表)的主要关键是User_Id和Vehicle_Id有什么后果?
在分布式系统网络中,时间是敌人。通过拥有两个表,您现在正在进行两个查询...假设用户与车辆的比率为1比1。但如果您的用户有8辆车,那么您现在需要9个查询才能获得结果。通过上面的设计,您可以在1个查询中构建结果集(最小化网络时间)。同样使用userid
作为分区键,该查询保证由一个节点提供服务,而不是对车辆数据的其他查询,这很可能需要联系多个节点。
答案 1 :(得分:1)
这看起来就像拥有两张桌子一样简单,一张桌子拿着你们所有的车辆数据,另一张桌子用于满足你的查询:
CREATE TABLE vehicles (
vehicle_id bigint,
vehicle_type int,
vehicle_name text,
...
PRIMARY KEY (vehicle_type)
)
CREATE TABLE vehicles_to_users (
user_id bigint,
vehicle_id bigint,
vehicle_type int,
vehicle_name text,
...
PRIMARY KEY (user_id, vehicle_type)
)
然后你会查询:
SELECT * FROM vehicles_to_users WHERE user_id = 9;
或类似的东西,以获得属于特定用户的所有特定车辆类型:
SELECT * FROM vehicles_to_users WHERE user_id = 9 AND vehicle_type = 1;
这是一个带有非规范化数据的解决方案,你应该始终考虑这种方法而不是像:
CREATE TABLE vehicles (
vehicle_id bigint,
vehicle_type int,
vehicle_name text,
...
PRIMARY KEY (vehicle_type)
)
CREATE TABLE vehicles_to_users (
user_id bigint,
vehicle_id bigint,
PRIMARY KEY (user_id)
)
因为它属于关系数据库世界而且您必须运行N + 1个查询以满足您的要求:一个用于获取属于特定用户的所有ID,然后是N个查询以获取每个用户的所有信息车辆:
SELECT * FROM vehicles_to_users WHERE user_id = 9;
SELECT * FROM vehicles WHERE vehicle_id = 115;
SELECT * FROM vehicles WHERE vehicle_id = 116;
SELECT * FROM vehicles WHERE vehicle_id = ...;
不要试图像这样使用IN
clausole:
SELECT * FROM vehicles WHERE vehicle_id IN (115,116,....);
因为协调器节点必须做的额外工作会使性能更差。