Cassandra中的一对多映射

时间:2016-09-07 14:01:20

标签: cassandra cassandra-2.0

我是Cassandra的新手,想要对用户及其车辆进行一对多的映射。一个用户可能有多个车辆。我的用户表将包含用户详细信息,如姓名,姓氏等。车辆表将包含车辆详细信息。

我的选择查询将获取特定用户的所有车辆详细信息。

我应该如何在Cassandra中设计这个?

2 个答案:

答案 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,....);

因为协调器节点必须做的额外工作会使性能更差。