卡桑德拉;关于指数的最佳做法?

时间:2013-12-11 15:04:42

标签: java cassandra

我正在对Cassandra架构进行建模,以便对该主题更加熟悉,并且想知道有关创建索引的最佳实践。

例如:

create table emailtogroup(email text, groupid int, primary key(email));
select * from emailtogroup where email='joop';
create index on emailtogroup(groupid);
select * from emailtogroup where groupid=2 ;

或者我可以创建一个完整的新表:

create table grouptoemail(groupid int, email text,  primary key(groupid, email));
select * from grouptoemail where groupid=2;

他们都做好了工作。

我希望创建一个新表更快,因为现在groupid成为分区键。但是我不确定创建索引时会发生什么“魔法”,如果这种魔法有下降的话。

2 个答案:

答案 0 :(得分:2)

这取决于groupid的基数。 cassandra docs

  

何时不使用索引

     

不要使用索引来查询大量的记录   结果数量。例如,如果您在a上创建索引   高基数列,它有许多不同的值,一个查询   在这两个领域之间会产生很多寻求很少结果的问题。在里面   有十亿用户的表,通过他们的电子邮件地址查找用户(a   每个用户通常唯一的值)而不是他们的   国家,可能是非常低效的。它可能会更多   高效地手动维护表作为索引的一种形式   使用Cassandra内置索引。对于包含唯一的列   数据,有时使用索引的性能很好   方便,只要查询到表中的卷就有了   索引列是适中的,不在恒定负载下。

     

当然,不支持计数器列,其中包括每个列   价值是截然不同的。

     

相反,在极低基数列上创建索引,   比如布尔列,没有意义。索引中的每个值   在索引中成为一行,导致所有的一行   例如,假值。索引大量索引列   foo = true和foo = false是没用的。

所以基本上,如果你打算处理一个大型数据集,而groupid不会返回很多行,那么二级索引可能不是最好的主意。

DataStax Academy's Java Developement with Apache Cassandra class第4周讨论如何有效地模拟这些问题。如果有机会,请检查一下。

答案 1 :(得分:2)

据我所知,你的第一种方法是正确的。

create table emailtogroup(email text, groupid int, primary key(email));

因为1)在您的情况下,电子邮件是一种独特的,良好的主键候选者和2)多个电子邮件可以属于同一组,是二级索引的良好候选者。请参阅此帖子 - Cassandra: choosing a Partition Key

分区键用于在不同节点之间分配数据,如果您希望节点平衡(即每个节点上分布均匀的数据),那么您希望分区键尽可能随机。

表创建的第二种形式对范围扫描很有用。例如,如果您有像

这样的用例

i)列出用户从2010年1月1日到2013年1月1日加入的所有电子邮件组。

在这种情况下,您可能需要设计一个类似

的表格
create table grouptoemail(email text, ts timestamp, groupid int, primary key(email, ts));

在这种情况下,用户加入的所有电子邮件gropus将聚集在磁盘上。(一起存储在磁盘上)