列族概念和数据模型

时间:2010-07-14 10:32:16

标签: nosql datamodel

我正在研究不同类型的NoSQL数据库类型,我正试图围绕列系列商店的数据模型,如Bigtable,HBase和Cassandra。

第一个模型

有些人将列系列描述为行集合,其中每行包含 [1],[2] 列。此模型的一个示例(列族是大写的):

{
  "USER":
  {
    "codinghorror": { "name": "Jeff", "blog": "http://codinghorror.com/" },
    "jonskeet": { "name": "Jon Skeet", "email": "jskeet@site.com" }
  },
  "BOOKMARK":
  {
    "codinghorror":
    {
      "http://codinghorror.com/": "My awesome blog",
      "http://unicorns.com/": "Weaponized ponies"
    },
    "jonskeet":
    {
      "http://msmvps.com/blogs/jon_skeet/": "Coding Blog",
      "http://manning.com/skeet2/": "C# in Depth, Second Edition"
    }
  }
}

第二个模型

其他网站将一个列系列描述为一行 [3],[4] 中的一组相关列。上一个示例中的数据以这种方式建模:

{
  "codinghorror":
  {
    "USER": { "name": "Jeff", "blog": "http://codinghorror.com/" },
    "BOOKMARK":
    {
      "http://codinghorror.com/": "My awesome blog",
      "http://unicorns.com/": "Weaponized ponies"
    }
  },
  "jonskeet":
  {
    "USER": { "name": "Jon Skeet", "email": "jskeet@site.com" },
    "BOOKMARK":
    {
      "http://msmvps.com/blogs/jon_skeet/": "Coding Blog",
      "http://manning.com/skeet2/": "C# in Depth, Second Edition"
    }
  }
}

第一个模型背后的一个可能的理由是,并非所有列系列都具有USERBOOKMARK之类的关系。这意味着并非所有列族都包含相同的键。从这个角度来看,将列族置于外层感觉更自然。

名称“列族”表示一组列。这正是列族在第二个模型中的呈现方式。

两种模型都是数据的有效表示。我意识到这些表示仅仅是为了向人类传播数据;应用程序不会以这种方式“思考”数据。

问题

列族的“标准”定义是什么?它是行的集合,还是行中的一组相关列?

我必须写一篇关于这个主题的论文,所以我也对人们通常如何向其他人解释“列族”概念感兴趣。这两种模型似乎都相互矛盾。我想使用“正确”或普遍接受的模型来描述列族商店。


更新

我已经使用第二个模型来解释我的论文中的数据模型。我仍然对如何向其他人解释列族商店的数据模型感兴趣。

3 个答案:

答案 0 :(得分:9)

我认为Cassandra数据库遵循您的第一个模型。 ColumnFamily是一组行,它们可以以稀疏的方式包含任何列(因此,如果需要,每行可以具有不同的列名集合)。连续允许的列数几乎是无限的(Cassandra v0.7中有20亿)。

关键是,根据定义,行键在列族中必须是唯一的 - 但可以在其他列族中重复使用。因此,您可以在不同的ColumnFamilies中存储有关相同密钥的不相关数据。

在Cassandra中,这很重要,因为特定列族中的数据存储在磁盘上的相同文件中 - 因此在同一ColumnFamily中放置可能一起检索的数据项更有效。这在一定程度上是一个实际的速度问题,但也是将数据组织成一个清晰的模式的问题。这涉及到您的第二个定义 - 可能会将有关特定键的所有数据都视为“行”,但会按列族进行分区。但是,在Cassandra中,它实际上不是一行,因为一个ColumnFamily中的数据可以独立于同一行键的其他ColumnFamilies中的数据进行更改。

答案 1 :(得分:5)

您描述的两种型号都是相同的。

列族是:

Key -> Key -> (Set of key/value pairs)

从概念上讲,它变成了:

Table -> Row -> (Column1/Value1, Column2/Value2, ...)

将其视为键/值对的映射图。

UserProfile = {
    Cassandra = [emailAddress:"cassandra@apache.org", age:20],
    TerryCho = [emailAddress:"terry.cho@apache.org", gender:"male"],
    Cath = [emailAddress:"cath@apache.org", age:20, gender:"female", address:"Seoul"],
}

以上是列族的示例。如果要对其进行制表,那么您将得到一个名为UserProfile的表,它看起来像:

UserName | Email | Age | Gender | Address
Cassandra | cassandra@apache.org | 20 | null | null
TerryCho | terry.cho@apache.org | null | male | null
Cath | cath@apache.org | 20 | female | Seoul

令人困惑的部分是,我们已经习惯于思考它们,而不是真正的列或行。那里有一堆"列系列"通过名称(密钥)查询。这些系列包含一组键/值对,也可以通过名称(行键)进行查询,最后,也可以通过名称(列键)查找集合中的每个值。

如果您需要表格参考点,"列族"将是你的"表"。每组" k / v对"在他们里面将是你的"行"。每对"对#34;将是"列名称及其值"。

在内部,每个列familly中的数据将被存储在一起,并且它将被存储使得行一个接一个地存储,并且在每一行中,列是一个接一个的。所以你得到row1 -> col1/val1, col2/val2, ... , row2 -> col1/val1 ... , ... -> ...。因此,从这个意义上讲,数据的存储更像是行存储,而不像列存储。

要完成,这里的词语选择是不幸和误导的。列族中的列应该被称为属性。行应该被称为属性集。列族应该被称为属性族。与经典表格词汇的关系是微弱和误导的,因为它实际上是非常不同的。

答案 2 :(得分:2)

根据我的理解,Cassandra ColumnFamily不是行的集合,而是列的集群。 列基于群集键聚集在一起。 例如, 让我们考虑下面的columnfamily:

CREATE TABLE store (
  enrollmentId int,
  roleId int,
  name text,
  age int,
  occupation text,
  resume blob,
  PRIMARY KEY ((enrollmentId, roleId), name)
) ;


INSERT INTO store (enrollmentid, roleid, name, age, occupation, resume)
values (10293483, 01, 'John Smith', 26, 'Teacher', 0x7b22494d4549);

使用cassandra-cli在上面插入详细信息,它基于聚类键很好地聚类,在这个例子中" name = John Smith"是群集密钥。

RowKey: 10293483:1
=> (name=John Smith:, value=, timestamp=1415104618399000)
=> (name=John Smith:age, value=0000001a, timestamp=1415104618399000)
=> (name=John Smith:occupation, value=54656163686572, timestamp=1415104618399000)
=> (name=John Smith:resume, value=7b22494d4549, timestamp=1415104618399000)