Cassandra 动态架构更改

问题描述

我有很多用户(150-2 亿)。每个用户有 N(30-100) 个属性。该属性可以是整数、文本或时间戳类型。属性未知,所以我想动态添加它们。

解决方案 1 - 通过更改表格添加新列

   CREATE TABLE USER_PROFILE(
    UID uuid PRIMARY KEY,LAST_UPDATE_DATE TIMESTAMP,CREATION_DATE TIMESTAMP
   );

对于每个新属性

    ALTER TABLE USER_PROFILE ADD AGE INT;
    INSERT INTO USER_PROFILE ( UID,LAST_UPDATE_DATE,CREATION_DATE,AGE) VALUES ('01f63e8b-db53-44ef-924e-7a3ccfaeec28',2021-01-12 07:34:19.121,27);

解决方案 2 - 固定架构:

CREATE TABLE USER_PROFILE(
    UID uuid,ATTRIBUTE_NAME TEXT,ATTRIBUTE_VALUE_TEXT TEXT,ATTRIBUTE_VALUE_TIMESTAMP TIMESTAMP,ATTRIBUTE_VALUE_INT INT,CREATION_DATE TIMESTAMP,PRIMARY KEY (UID,ATTRIBUTE_NAME)
);

对于每个新属性

INSERT INTO USER_PROFILE ( UID,ATTRIBUTE_NAME,ATTRIBUTE_VALUE_INT,CREATION_DATE) VALUES ('01f63e8b-db53-44ef-924e-7a3ccfaeec28','age',27,27);

性能而言,哪个解决方案最好?

解决方法

我个人会采用第二种解决方案 - 为所使用的每种数据类型设置列,并使用属性名称作为主键的最后一个组件(参见我之前关于该主题的答案中的示例:

第一个解决方案有以下问题:

  • 如果您从代码中修改架构,那么您需要协调这些更改,否则您将获得 schema disagreement,管理员必须通过重新启动节点来解决该问题。协调的更改要么会减慢数据插入的速度,要么会造成单点故障
  • 多列的存在会对性能产生重大影响。例如,对于 this very good analysis by The Last Pickle,拥有 100 列而不是 10 列会使读取延迟增加 10 倍以上
  • 如果需要,您不能更改属性类型 - 在将属性作为聚类列的解决方案中,您可以开始将属性作为另一种类型。如果您将属性作为列,则不能这样做,因为 Cassandra 不允许更改列类型(不要尝试删除列并将其添加回新类型 - 您会破坏现有数据)。因此,您需要为该属性创建一个全新的列。