我一再听说二手索引(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)
);
答案 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索引。