在Cassandra中组织范围扫描的行键的方法

时间:2012-01-31 19:32:31

标签: database-design cassandra phpcassa

我正在尝试找到一种很好的方法来组织我的行键来对它们执行范围扫描而不创建我自己的索引列表。

我有一个MySQL数据库,目前有大约15.000个数据库,每个~50个表= 75.000个表。因为99%的数据总是使用唯一标识符读取,因此计划将数据移动到Cassandra集群中。

对于某些维护(列出完整表的内容,删除完整的表或删除数据库),我需要获取完整表甚至数据库的内容。范围扫描似乎是最适合的。

目前我计划为旧结构的每个部分生成UUID,并将它们分隔为|(DB + Table + Id = UUID1 | UUID2 | UUID2)。

示例:

07424eaa-4761-11e1-ac67-12313c033ac4|0619a6ec-4525-11e1-906e-12313c033ac4|0619a6ec-4795-12e9-906e-78313c033ac4

带有数据的CF应该使用org.apache.cassandra.db.marshal.AsciiType进行排序。

作为客户我正在使用phpcassa。

对于范围扫描,我想使用UUID|作为开始键,作为范围的结尾,使用相同的键,但附加chr(255)z。两个字符的ascii值都比该键中的任何其他UUID字符大。

这是一种可靠的方法,可以让我实现范围扫描的解释目标吗?

1 个答案:

答案 0 :(得分:5)

Cassandra最佳实践是使用RandomPartitioner - 只要您的令牌均匀分布,这就可以实现'免费'负载平衡。不幸的是,对于随机分区器,行范围查询(即get_range_slices)以随机顺序返回键。

这适用于遍历整个列族(如果这是您想要的,那么您的方法将起作用)。但是,如果您只想浏览较小的,连续的行键范围,它将无法正常工作。

解决此问题的一个选择是使用宽行和复合列。例如,列族如下所示:

{ 
  row1 -> {column1: value1, column2: value2},
  row2 -> {column3: value3, column4: value4},
  ... 
}

将转换为如下所示:

{
  row1-10 -> {
              [row1, column1]: value1, [row1, column2]: value2,
              [row2, column3]: value3, [row2, column4]: value4,
              ...
             }
  ...
}

您可以通过在右侧列之间的右侧列上执行列切片(get_slice)来执行范围查询。即

get_range_slice(start=row1, end=row2)

变为:

get_slice(row=row1-10, start=[row1, null], end=[row2, null])

请注意列键上的第二个空维。

诀窍是选择你的行('bucket')键,这样你的列就不会变得太大(这对普通的Cassandra来说会很糟糕),但是你查询的行不需要太多。这取决于你的平均查询大小和uuids的分布,但一个好的候选者可能是使用UUID1作为行键,[UUID2,UUID3]作为列键的第一个维度。