Cassandra:选择分区键

时间:2013-08-11 03:12:13

标签: cassandra composite-primary-key database-partitioning database-indexes

我不确定使用非常常见的共享列值(如Country)作为复合主键的分区键还是相当独特的列值(如{{1}更好,性能更好}})。

Cassandra 1.2's documentation about indexes我明白了:

  

何时使用索引:   Cassandra的内置索引在桌面上是最好的   有许多行包含索引值。 越独特   特定列中存在的值,您将产生更多的开销   平均而言,要查询和维护索引。例如,   假设您有一个拥有十亿用户的用户表并希望查看   通过他们所居住的州来提升用户。许多用户将共享相同的内容   状态的列值(例如CA,NY,TX等)。这将是一个   索引的良好候选人。

     

何时不使用索引:   不要使用索引来查询大量的记录   结果数量。例如,如果在列上创建索引   具有许多不同的值,字段之间的查询将产生   许多人寻求的结果很少。 在拥有十亿用户的表格中,   通过他们的电子邮件地址查找用户(通常是一个值)   每个用户都是独一无二的)而不是他们的状态,很可能是非常的   低效。手动维护可能更有效   表作为索引的一种形式,而不是使用Cassandra   内置索引。对于包含唯一数据的列,有时也是如此   为了方便起见,使用索引的性能很好,只要   具有索引列的表的查询量是适中的而不是   在恒定负荷下。“

Looking at the examples from CQL's SELECT

查询复合主键并对结果进行排序”,我看到UUID被用作分区键... ,这表明最好使用一些相当独特的东西

enter image description here

3 个答案:

答案 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>>

因此记录将按顺序存储在内存中。