【问题标题】:Cassandra need for IN clause in consideration of a messaging application考虑到消息传递应用程序,Cassandra 需要 IN 子句
【发布时间】:2021-10-17 08:01:27
【问题描述】:

对于消息传递应用程序,我的数据库结构相对于:

CREATE TABLE users(
    userid text,
    name text, 
    rooms list<text>
    ...
    PRIMARY KEY (userid)
);

CREATE TABLE rooms(
    roomid text,
    members list<text>,
    createdat bigint,
    lastmessage bigint,
    ...
    PRIMARY KEY (roomid, createdat)
);

CREATE TABLE messages(
    roomid text,
    bucket int,
    messageid bigint,
    authorid text,
    ...
    PRIMARY KEY ((hash, roomid), messageid)
);

客户端在启动时为给定用户请求所有房间。首先,我使用以下命令查询给定用户的所有 roomid:

SELECT rooms FROM users WHERE userId = 1234

然后我使用 IN 子句收集所有房间

SELECT * FROM rooms WHERE roomid IN ('room_1', 'room_2', ......);

并将实体返回给客户端。

我研究过,IN 子句可能导致一个节点承受很大压力。我希望用户拥有多达 100 个房间。

我必须将请求拆分为单个查询还是它们的另一种方式类似于更改数据模型?

为什么IN子句会导致单节点压力?

提前致谢!

【问题讨论】:

    标签: cassandra cql cassandra-3.0 cql3


    【解决方案1】:

    您是正确的,您应该限制 IN() 运算符中的键数。我通常建议使用非常低的个位数的键,例如 2 或 3,不要太多,否则协调器将承受很大的压力,因为它必须触发尽可能多的单独请求。

    您是对的,您应该对数据进行不同的建模以获得最佳性能。

    我强烈建议创建一个按用户 ID 分区的新表:

    CREATE TABLE rooms_by_userid (
      ...
      PRIMARY KEY (userid, roomid)
    )
    

    当您使用以下方式查询表时:

    SELECT ... FROM rooms_by_userid WHERE userid = 1234
    

    您将获得按房间 ID 分组的数据行。这是对数据建模的最佳方式,因为它是根据应用要求进行组织的。

    您当前的模型实际上是通过查询 2 个表来执行笨拙的 JOIN。我建议的方式意味着您只需要从一个表中检索数据,因此它非常有效。干杯!

    【讨论】:

    • 我知道我应该始终按照您的建议在查询之后设计我的表格。毕竟我在过去几周读过,在 cassandra 中对模型进行非规范化似乎更好,尽管这意味着我必须写入/更新更多数据。在这种情况下,例如当我更新房间名称时,我必须为房间的每个成员更新房间名称列。这是常见的做法吗?感谢埃里克·拉米雷斯
    • 是的,这是很常见的做法,在 Cassandra 中也是如此。干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 2015-12-03
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多