15

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

考虑这个例子:

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

现在我不能做这个查询,除非我在users on 上创建一个二级索引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) 
    );
4

3 回答 3

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 (...);

希望这可以帮助

于 2014-08-06T16:24:21.123 回答
4

有几种方法可以做到这一点,各有利弊。

  • 您的第二个查询将起作用,但它只是一个索引表。http://wiki.apache.org/cassandra/SecondaryIndexes 二级索引可能会有所帮助,如果你先点击一个分区(你不能在你的第一个表中这样做),那么 cassandra 的实现将为你省去麻烦,并保持“局部原子”的东西。但是,如果不命中分区,则带有索引的第一个表对您的查询不会很好,因为它会在任何地方命中所有内容。

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

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

  • 您的索引可能是名字的前几个字符。或者它可能是一个一致的散列到几个桶中。前者可以给你“开始于”语义。

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

于 2014-08-05T04:02:46.987 回答
0

还有具有自动更新的物化视图,可将数据分区到不同的列上,因此可以更快地读取并完全避免二级索引。自己做这件事还有一些额外的好处。

避免热分区的总体思路仍然存在。

然后,如果您对物化视图主键进行大量更新以避免墓碑,那么还有 SASI 索引。

于 2018-04-19T20:02:26.260 回答