列族概念和数据模型
Posted
技术标签:
【中文标题】列族概念和数据模型【英文标题】:Column-family concept and data model 【发布时间】:2011-03-15 18:54:30 【问题描述】:我正在研究不同类型的 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"
第一个模型背后的一个可能原理是,并非所有列族都具有像 USER
和 BOOKMARK
这样的关系。这意味着并非所有列族都包含相同的键。从这个角度来看,将列族放在外层感觉更自然。
“列族”这个名称意味着一组列。这正是第二个模型中列族的呈现方式。
两种模型都是数据的有效表示。我意识到这些表示仅用于将数据传达给人类;应用程序不会以这种方式“思考”数据。
问题
什么是列族的“标准”定义?它是行的集合,还是一行中的一组相关列?
我必须写一篇关于这个主题的论文,所以我也对人们通常如何向其他人解释“列族”概念感兴趣。这两种模式似乎相互矛盾。我想使用“正确”或普遍接受的模型来描述列族商店。
更新
我已经选择了第二个模型来解释我论文中的数据模型。我仍然对你如何向其他人解释列族存储的数据模型感兴趣。
【问题讨论】:
+1 很棒的帖子,如果您的论文在线可用,我很乐意阅读(如果可以,请更新帖子)。 @tbone 谢谢!该论文无法在线获得,但如果我有时间,我可能会将其中的部分内容转换为博客文章。 【参考方案1】:你描述的两个模型都是一样的。
列族是:
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 对”都是您的“行”。每个“集合对”都是“列名及其值”。
在内部,每个列族内的数据将被存储在一起,并且会以行一个接一个的方式存储,并且在每一行中,列一个接一个。所以你得到row1 -> col1/val1, col2/val2, ... , row2 -> col1/val1 ... , ... -> ...
。所以从这个意义上说,数据的存储更像是行存储,而不是列存储。
最后,这里的措辞令人遗憾和误导。列族中的列应该被称为属性。行应该被称为属性集。列族应该被称为属性族。与经典表格词汇的关系很弱且具有误导性,因为它实际上完全不同。
【讨论】:
【参考方案2】:据我了解,Cassandra 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)
【讨论】:
【参考方案3】:我认为 Cassandra 数据库遵循您的第一个模型。 ColumnFamily 是行的集合,它可以以稀疏的方式包含任何列(因此,如果需要,每行可以具有不同的列名集合)。一行中允许的列数几乎是无限的(Cassandra v0.7 中为 20 亿)。
一个关键点是,根据定义,行键在列族中必须是唯一的,但可以在其他列族中重复使用。因此,您可以将关于同一键的不相关数据存储在不同的 ColumnFamilies 中。
在 Cassandra 中,这很重要,因为特定列族中的数据存储在磁盘上的相同文件中 - 因此将可能一起检索的数据项放在同一个 ColumnFamily 中会更有效。这部分是实际的速度问题,也是将数据组织成清晰模式的问题。这触及了您的第二个定义 - 人们可能会将有关特定键的所有数据视为“行”,但按列族进行分区。然而,在 Cassandra 中它并不是真正的单行,因为一个 ColumnFamily 中的数据可以独立于其他 ColumnFamilies 中的数据更改为相同的行键。
【讨论】:
感谢您分享您对此的看法!我的结论是,这没有对错,你的回答只是证实了这一点。它基本上是一个二维(或三)维矩阵,就像传统的数据库表一样,但由于内容的稀疏性,它不适合通常的表格格式:)以上是关于列族概念和数据模型的主要内容,如果未能解决你的问题,请参考以下文章