我不确定使用非常常见的共享列值(如Country
)作为复合主键的分区键还是相当独特的列值(如{{1}更好,性能更好}})。
看Cassandra 1.2's documentation about indexes我明白了:
“何时使用索引: Cassandra的内置索引在桌面上是最好的 有许多行包含索引值。 越独特 特定列中存在的值,您将产生更多的开销 平均而言,要查询和维护索引。例如, 假设您有一个拥有十亿用户的用户表并希望查看 通过他们所居住的州来提升用户。许多用户将共享相同的内容 状态的列值(例如CA,NY,TX等)。这将是一个 索引的良好候选人。“
“何时不使用索引: 不要使用索引来查询大量的记录 结果数量。例如,如果在列上创建索引 具有许多不同的值,字段之间的查询将产生 许多人寻求的结果很少。 在拥有十亿用户的表格中, 通过他们的电子邮件地址查找用户(通常是一个值) 每个用户都是独一无二的)而不是他们的状态,很可能是非常的 低效。手动维护可能更有效 表作为索引的一种形式,而不是使用Cassandra 内置索引。对于包含唯一数据的列,有时也是如此 为了方便起见,使用索引的性能很好,只要 具有索引列的表的查询量是适中的而不是 在恒定负荷下。“
Looking at the examples from CQL's SELECT
“查询复合主键并对结果进行排序”,我看到UUID被用作分区键... ,这表明最好使用一些相当独特的东西
答案 0 :(得分:40)
您编写的文档中的索引是指二级索引。在cassandra中有一个difference between the primary and secondary indexes。对于二级索引,拥有非常独特的值确实很糟糕,但是对于主键中的组件,这取决于我们关注的组件。在主键中,我们有以下组件:
PRIMARY KEY(分区键,群集key_1 ...群集key_n)
分区键用于在不同节点之间分配数据,如果您希望节点平衡(即每个节点上分布均匀的数据),那么您希望分区键尽可能随机。这就是为什么您使用UUID的原因。
群集密钥使用进行排序,以便使用特定群集密钥查询列可以更高效。在这里,您希望您的值不是唯一的,并且如果频繁出现唯一的行,那么性能会受到影响。
cql docs对正在发生的事情有一个很好的解释。
答案 1 :(得分:8)
如果你使用cql3,给定一个列族:
CREATE TABLE table1 (
a1 text,
a2 text,
b1 text,
b2 text,
c1 text,
c2 text,
PRIMARY KEY ( (a1, a2), b1, b2) )
);
通过定义一个 主键((a1,a2,...),b1,b2,...)
这意味着:
a1,a2,...是用于制作行键的字段,以便:
b1,b2,...是列族字段,用于聚类行键以便:
对于每个可能的列键组合,所有剩余的字段都被有效地多路复用/复制。下面是一个关于具有分区键和聚类键的复合键的示例。
如果要使用范围查询,可以使用辅助索引或(从cql3开始)可以将这些字段声明为聚类键。在速度方面,将它们作为聚类键将创建一个宽行。这会影响速度,因为您将获取多个群集键值,例如:
select * from accounts where Country>'Italy' and Country<'Spain'
答案 2 :(得分:1)
我相信你会得到答案,但这仍然可以帮助你更好地理解。
CREATE TABLE table1 (
a1 text,
a2 text,
b1 text,
b2 text,
c1 text,
c2 text,
PRIMARY KEY ( (a1, a2), b1, b2) )
);
这里的分区键是(a1,a2),行键是b1,b2。
对于每个新记录条目,分区键和行键的组合必须是唯一的。
上面的主键可以像这样定义。
Node< key, value>
Node<(a1a2), Map< b1b2, otherColumnValues>>
我们知道分区键负责整个节点的数据分发。
因此,如果您在table1中插入具有相同分区键和不同行键的100条记录。它会将数据存储在同一节点但不同的列中。
逻辑上我们可以这样表示。
Node<(a1a2), Map< string1, otherColumnValues>, Map< string2, otherColumnValues> .... Map< string100, otherColumnValues>>
因此记录将按顺序存储在内存中。