在互联网上阅读几篇论文和文档,我发现了许多关于Cassandra数据模型的矛盾信息。有许多将其识别为面向列的数据库,其他作为面向行的数据库,然后将其定义为两者的混合方式。
根据我对Cassandra如何存储文件的了解,它使用* -Index.db文件访问* -Data.db文件的正确位置,在该文件中存储了bloom过滤器,列索引然后是所需行的列。
在我看来,这是严格按行的。有什么我想念的吗?
答案 0 :(得分:51)
是的,“以列为导向”的术语有点令人困惑。
Cassandra中的模型是行包含列。要访问最小的数据单元(列),您必须先指定行名(键),然后指定列名。
因此,在名为Fruit
的列系列中,您可以使用类似以下示例的结构(包含2行),其中水果类型是行键,每列都有名称和值。
apple -> colour weight price variety
"red" 100 40 "Cox"
orange -> colour weight price origin
"orange" 120 50 "Spain"
与基于表的关系数据库的一个区别是,可以省略列(橙色没有变化),或者随时添加任意列(橙色具有原点)。您仍然可以将上面的数据想象为一个表,尽管是一个稀疏的数据可能是空的。
但是,“面向列的”模型也可以用于列表和时间序列,其中每个列名都是唯一的(这里我们只有一行,但我们可能有数千或数百列):
temperature -> 2012-09-01 2012-09-02 2012-09-03 ...
40 41 39 ...
与关系模型完全不同,后者必须将时间序列的条目建模为rows
而不是columns
。这种用法通常被称为“宽行”。
答案 1 :(得分:39)
Cassandra是一个分区行存储。行被组织成表格 使用必需的主键。
分区意味着Cassandra可以分发您的数据 应用程序透明的多个机器。卡桑德拉会 在添加和删除计算机时自动重新分区 群集。
行存储意味着像关系数据库一样,Cassandra组织 按行和列的数据。
面向列或列式数据库以列方式存储在磁盘上。
例如:表Bonuses
表
ID Last First Bonus
1 Doe John 8000
2 Smith Jane 4000
3 Beck Sam 1000
在面向行的数据库管理系统中,数据将按如下方式存储:1,Doe,John,8000;2,Smith,Jane,4000;3,Beck,Sam,1000;
在面向列的数据库管理系统中,数据将按如下方式存储:
1,2,3;Doe,Smith,Beck;John,Jane,Sam;8000,4000,1000;
Cassandra基本上是一个列族商店
"Bounses" : {
row1 : { "ID":1, "Last":"Doe", "First":"John", "Bonus":8000},
row2 : { "ID":2, "Last":"Smith", "First":"Jane", "Bonus":4000}
...
}
希望这有帮助。
答案 2 :(得分:10)
你们都提出了好的观点,这可能令人困惑。在示例中
apple -> colour weight price variety
"red" 100 40 "Cox"
apple是键值,列是数据,包含所有4个数据项。从描述中可以看出,所有4个数据项一起存储为单个对象,然后由应用程序解析以提取所需的值。因此,从IO的角度来看,我需要读取整个对象。恕我直言,这本质上是基于行(或对象)而不是基于列。
基于列的存储在仓库中变得流行,因为它为全表扫描(DW)提供极端压缩和减少的IO,但是当您需要拉动每一列(选择*)时,以增加IO的IO为代价。大多数查询不需要每列,并且由于压缩,只需几列就可以大大减少IO的全表扫描。让我举个例子
apple -> colour weight price variety
"red" 100 40 "Cox"
grape -> colour weight price variety
"red" 100 40 "Cox"
我们有两种不同的水果,但都有颜色=红色。如果我们将颜色存储在单独的磁盘页面(块)中,不受重量,价格和变化的影响,那么唯一存储的就是颜色,那么当我们压缩页面时,由于大量的重复数据删除,我们可以实现极端压缩。我们可以存储10,000种颜色,而不是在页面中存储100行(假设)。现在要读取所有颜色为红色的内容,它可能是1 IO而不是数千个IO,这对于仓储和分析非常有用,但如果我需要更新整个行,那么OLTP会很糟糕,因为该行可能有数百列和一个更新(或插入)可能需要数百个IO。
除非我遗漏了一些我不会称之为柱状的东西,否则我称之为基于对象。关于如何在磁盘上排列对象仍然不清楚。多个对象是否放在同一磁盘页面中?有没有办法确保具有相同元数据的对象一起使用?至于一个水果可能包含不同于另一个水果的数据,因为它只是元数据或xml或者你想要存储在对象本身中的任何东西,是否有办法确保某些匹配的水果类型存储在一起以提高效率?
拉里
答案 3 :(得分:4)
列系列并不意味着它是面向列的。 Cassandra是专栏系列,但不是专栏。它将行及其所有列族存储在一起。
Hbase是列族,也是以列为导向的方式存储列族。不同的列族分别存储在节点中,或者它们甚至可以驻留在不同的节点中。
答案 4 :(得分:4)
我遇到的最明确的术语是宽栏商店。
这是一种二维键值存储,您可以使用行键和列键来访问数据。
此模型与关系型(面向行和列导向)之间的主要区别在于列信息是数据的一部分。
这意味着数据可以稀疏。这意味着不同的行不需要共享相同的列名或列数。这可以实现半结构化数据或无架构表。
您可以将宽列商店视为可以容纳无限数量列的表格,因此广泛。
这里有几个链接来支持这个:
答案 5 :(得分:1)
Cassandra具有列族(表)的概念,该概念最初来自BigTable。但是,正如您提到的那样,将它们称为面向列确实是一种误导。在每个列族中,它们将一行中的所有列以及行键一起存储,并且不使用列压缩。因此,Bigtable模型仍然主要是面向行的。
答案 6 :(得分:0)
IMO是Cassandra所用的错误术语。相反,将其称为行分区存储更为合适。让我为您提供一些详细信息:
主键,分区键,聚类列和数据列:
每个表必须具有唯一约束的主键。
Primary Key = Partition key + Clustering Columns
# Example
Primary Key: ((col1, col2), col3, col4) # primary key uniquely identifies a row
# we need to choose its components partition key
# and clustering columns so that each row can be
# uniquely identified
Partition Key: (col1, col2) # decides on which node to store the data
# partitioning key is mandatory, and it
# can be made up of one column or multiple
Clustering Columns: col3, col4 # decides arrangement within a partition
# clustering columns are optional
分区键是主键的第一部分。其哈希值用于确定要存储数据的节点。分区键可以是由多列组成的复合键。我们想要几乎相等的数据传播,并且在选择主键时要牢记这一点。
主键中分区键之后列出的任何字段都称为集群列。这些将数据按升序存储在分区中。集群列组件还有助于确保每一行的主键都是唯一的。
您可以根据需要使用任意数量的聚类列。您不能在SELECT语句中无序使用聚类列。您可以选择在SELECT语句中使用群集列来省略。没关系。只要记住在使用SELECT语句时依次起诉即可。但是请注意,在CQL查询中,如果未使用其他定义的聚类列,则无法尝试访问列或聚类列。例如,如果主键为(year, artist_name, album_name)
,并且您想在查询的city
子句中使用WHERE
列,那么只有在您的WHERE
子句使用所有属于主键的列。
令牌:
Cassandra使用令牌来确定哪个节点保存哪些数据。令牌是64位整数,Cassandra将这些令牌的范围分配给节点,以便每个可能的令牌归节点所有。在群集中添加更多节点或删除旧节点会导致在节点之间重新分配这些令牌。
行的分区键用于使用给定的分区程序(用于计算分区键的令牌的哈希函数)来计算令牌,以确定哪个节点拥有该行。
Cassandra是行分区存储:
行是在Cassandra中存储相关数据的最小单位。
不要将Cassandra的列族(即表)视为RDBMS表,而应将其视为{{的 {{1} 1}} (此处dict
是类似于Python dict
的数据结构):
dict
由行键(主键)键入:这确定分区中的哪个分区和哪一行OrderedDict
由列键(数据列)键入键:这是dict
中的数据,以列名作为键dict
均按键排序并排序:外部dict
按主键排序该模型允许您随时省略列或添加任意列,因为它允许您为不同的行使用不同的数据列。