我正在对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成为分区键。但是我不确定创建索引时会发生什么“魔法”,如果这种魔法有下降的话。
答案 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将聚集在磁盘上。(一起存储在磁盘上)