如何避免cassandra中的二级索引?

时间:2014-08-04 18:15:07

标签: cql3 cassandra-2.0 secondary-indexes

我一再听说二手索引(cassandra)只是为了方便而不是为了获得更好的性能。建议在基数较低时使用二级索引的唯一情况(例如性别column,其中有两个值为男性或女性)

考虑这个例子:

CREATE TABLE users ( 
userID uuid, 
firstname text, 
lastname text, 
state text, 
zip int, 
PRIMARY KEY (userID) 
);

现在我无法执行此查询,除非我在users上的firstname index上创建了二级索引

select * from users where firstname='john'

如何对此表进行非规范化,以便我可以拥有此查询: 这是使用复合键的唯一有效方法吗? 还有其他选择或建议吗?

CREATE TABLE users ( 
    userID uuid, 
    firstname text, 
    lastname text, 
    state text, 
    zip int, 
    PRIMARY KEY (firstname,userID) 
    );

3 个答案:

答案 0 :(得分:19)

为了提供良好的数据模型,您需要确定要执行的第一个 所有 查询。如果您只需要按名字(或名字和用户ID)查找用户,那么您的第二个设计就可以了......

如果您还需要按姓氏查找用户,则可以创建另一个表,该表具有相同的字段,但主键位于(lastname,userID)。显然,您需要在同一时间更新两个表。 Cassandra的数据复制很好。

但是,如果您担心两个或更多表所需的空间,您可以创建一个按用户ID分区的单个用户表,以及要查询的字段的其他表:

CREATE TABLE users ( 
    userID uuid, 
    firstname text, 
    lastname text, 
    state text, 
    zip int, 
    PRIMARY KEY (userID) 
);

CREATE TABLE users_by_firstname (
    firstname text,
    userid uuid,
    PRIMARY KEY (firstname, userid)
);

此解决方案的缺点是您需要两个查询来按名字检索用户:

SELECT userid FROM users_by_firstname WHERE firstname = 'Joe';
SELECT * FROM users WHERE userid IN (...);

希望这有帮助

答案 1 :(得分:4)

有一些方法可以做到这一点,都有利有弊。

  • 您的第二个查询将起作用,但它只是一个索引表。 http://wiki.apache.org/cassandra/SecondaryIndexes 辅助索引可能会有所帮助,如果您首先访问某个分区(在第一个表中无法执行),那么cassandra的实现将为您节省麻烦,并保持“本地原子”。虽然没有点击分区,你的第一个带索引的表对你的查询来说不会很好,因为它会触及所有地方。

  • 您可以完全非规范化,但您也可以查找表格。即您的第二个表只能存在以返回用户ID。然后,您可以执行第二次查询以仅获取相关分区的信息。如果您期望得到的结果很少,这可能会很好。如果没有,您将在许多节点上击中许多分区(这取决于您的群集大小和热点避免标准,可能是好的还是坏的)。进行多次~1ms查询通常比进行一次~1000ms查询更好。

  • 您可以进行人工分组,并发出n = bucketcount查询。这有额外的开销,但减少了查询次数,可能是一个不错的选择。

  • 您的索引可能是名字的前几个字符。或者它可能是几个桶中的一致哈希。前者可以给你“开头”的语义。

这些只是几个选项。从逻辑数据模型到物理数据模型需要评估您希望进行哪些权衡。

答案 2 :(得分:0)

还有具有自动udpates的物化视图,可以在不同的列上对数据进行分区,因此可以更快地读取并完全避免二次索引。这样做有一些额外的好处。

避免热分区的一般想法仍然存在。

然后,如果您在物化视图主键上进行大量更新以避免使用逻辑删除,那么还有SASI索引。