在Cassandra中映射冗余

时间:2016-09-19 20:22:35

标签: database database-design cassandra cassandra-3.0

输入:表格数据文件:每个文件具有可变数量的列,这些列名称可能对文件是唯一的和/或在其他文件之间共享(事先未知)。这些数据预计不会改变,因此插入频繁,但更新很少。列及其相关值可以是文本或数字。

请求的功能:能够按标识或范围进行查询,以检索给定列名和值的数据行。

数据模型:在CQL我可以使用表示文件特定单元格值的单个表进行建模(在本例中为文本,但可以为数字数据构建类似的表) )

create table mytable(
    colname text,
    value text,
    filename text,
    rowid int,
    data map<text,text>,
    primary key (colname , value, filename, rowid)#partitioning on colname may not be ideal here, but will be dealt with in ways unrelated to this question
);

例如,一个文件的内容可能是:

A   B   C   D   E
i1  i2  i3  i4  i5

插入内容为:

insert into mytable(colname, value, data, filename, rowid) values ('A', 'i1', {'A':'i1', 'B':'i2', 'C':'i3', 'D':'i4', 'E':'i5', 'F':'i5'}, 'F1', 1);
insert into mytable(colname, value, data, filename, rowid) values ('B', 'i2', {'A':'i1', 'B':'i2', 'C':'i3', 'D':'i4', 'E':'i5', 'F':'i5'}, 'F1', 2);
insert into mytable(colname, value, data, filename, rowid) values ('C', 'i3', {'A':'i1', 'B':'i2', 'C':'i3', 'D':'i4', 'E':'i5', 'F':'i5'}, 'F1', 3);
insert into mytable(colname, value, data, filename, rowid) values ('D', 'i4', {'A':'i1', 'B':'i2', 'C':'i3', 'D':'i4', 'E':'i5', 'F':'i5'}, 'F1', 4);
insert into mytable(colname, value, data, filename, rowid) values ('E', 'i5', {'A':'i1', 'B':'i2', 'C':'i3', 'D':'i4', 'E':'i5', 'F':'i5'}, 'F1', 5);
...

SELECT data from mytable where colname=? and value=?

问题:我们确实有数据存储限制 - 在此模型中,行的每个列值的数据值相同,导致大量过多的数据重复(这是一个简单的示例,但是列数可能超过100 - 意味着地图可以复制数百次。

问题: Cassandra有没有办法避免这种类型的数据重复而无需创建/查询第二个表(例如通过指向数据的指针)或以某种方式将地图定义为不同的)?或者,使用相同的查询功能和结果对数据进行建模的不同方法是什么?

1 个答案:

答案 0 :(得分:1)

如果您的设计受益于C *内置压缩,我不会感到惊讶,您的存储要求可能远低于您的预期。

顺便说一句,如果你想要一个完全不同的模型,你可以尝试:

  • 输入数据的每列一个表
  • 每个表都有一个分区键,它是您正在寻找的值

这些方面的东西:

CREATE TABLE colname_A (
    value text,
    data map<text,text>,
    ...,
    PRYMARY KEY (value)
);

CREATE TABLE colname_B (
    value text,
    data map<text,text>,
    ...,
    PRYMARY KEY (value)
);
....
CREATE TABLE colname_xxx (...);

然后您可以通过发出以下内容来选择您的数据:

SELECT * FROM colname_A WHERE value = 'i5';
SELECT * FROM colname_A WHERE value IN ('i4', 'i5')

请谨慎使用分区键中IN clausole的查询,因为您希望在将数据加载到群集时避免this等问题。

该模型以不同的方式组织数据,并受益于列间数据复制而不是行间数据复制。如果您有不平衡列(例如某些列中的大量记录),则此数据组织提供的压缩可能是一个巨大的胜利。