Cassandra 中的一对多映射

One to many mapping in Cassandra

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

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

我应该如何在 Cassandra 中设计它?

这看起来就像有两个表一样简单,一个包含您所有的车辆数据,另一个用于满足您的查询:

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 子句:

SELECT * FROM vehicles WHERE vehicle_id IN (115,116,....);

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

您可以轻松地在单个模型中对此进行建模 table:

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 辆车),这应该就可以正常工作。

The case I have considered above is very simple. But what if my User has lot of details around 20 to 30 fields and same for Vehicle. Still you would suggest to have a single table and copying User data for all vehicle?

视情况而定。您的用例是否需要返回所有这些?如果是这样,那么 "yes" 我仍然会推荐这种方法。从 Cassandra 获得最佳查询性能的方法是为您的 table 建模以适合您的查询。当 Cassandra 可以通过特定键或一系列行(按顺序存储)读取单行时,它的效果最好。您希望避免执行多个查询或编写强制 Cassandra 执行随机读取的查询。

What are the consequences of having 2 different tables like User and Vehicle and Vehicle table will have primary key as User_Id and Vehicle_Id?

在分布式系统网络中,时间就是敌人。通过有两个 table,您现在正在进行两个查询...假设用户与车辆的比例为 1 比 1。但是如果您的用户有 8 辆车,您现在需要 9 次查询才能获得结果。使用上面的设计,您可以在 1 个查询中构建结果集(最小化网络时间)。同样使用 userid 作为分区键,该查询保证由一个节点提供服务,而不是对车辆数据的额外查询,后者很可能需要联系多个节点。