我的架构是:
A)
CREATE TABLE friend_list (
userId uuid,
friendId uuid,
accepted boolean,
ts_accepted timestamp,
PRIMARY KEY ((userId) ,accepted, ts_accepted)
) with clustering order by (accepted desc, ts_accepted desc);
B)
CREATE TABLE friend_list (
userId uuid,
friendId uuid,
accepted boolean,
ts_accepted timestamp,
PRIMARY KEY (userId , ts_accepted)
) with clustering order by (ts_accepted desc);
CREATE INDEX ON friend_list (accepted);
这将为查询提供最佳性能:
SELECT * FROM friend_list WHERE userId="---" AND accepted=true;
根据我的理解,Cassandra会自动按ASC顺序对聚簇列进行排序,如果我们需要更改默认排序顺序以便进行有效查询,我们会指定DESC。
使用我的架构A,我正在接受'作为一个集群密钥,但我需要对其进行不必要的排序,因为我必须对它进行排序' ts_accepted'到DESC。 这种不受欢迎的排序是否会被接受'影响绩效?
如果是这样,请说我正在接受'作为模式B中的二级索引。我知道二级索引对于低基数值(布尔值)并不坏。但是查询可能仍有一些性能问题。
请告诉我实现此查询的有效方法。
答案 0 :(得分:2)
我去找A。
如果你可以避免使用二级索引,那就避免它(例外:你知道它将成为一个可以从中受益的火花工作)。如果您仍需要二级索引,请重新设计模型。如果你仍然需要它,内心感觉很恐怖,那么也许可以考虑一下。
您担心的聚类顺序的成本并不合适。 Cassandra存储聚类列,无论如何... ASC或DESC不会改变事物。您使用了更多空间,但是对于您的查询,您希望点击“#34;已接受"”,因此它是合理的。我猜其他原因需要ts_accepted吗?这里唯一的问题是,如果您在查询中需要或有权访问ts_accepted,则需要提供一个可接受的相等过滤器。表现明智,我没有看到问题。
至于B,极低基数列(如bool)的索引很糟糕。考虑如何存储数据 - 对于每个节点,Cassandra维护一个表,其中键是值(true / false),值是该节点匹配键的所有数据的键。这有可能成为一个非常广泛的专栏。如果你要为一个单独的表建模,你会这样做吗?不,你也不应该用索引做到这一点。
我不知道剩下的数据,但如果你想找到被接受的朋友,为什么还要用布尔值呢?您可以使用ts_accepted列来推断布尔值。如果他们有价值,那就接受吧?
您应该注意的一件事是,您无法更新pk的一部分列。
最后,您正在查询查询的分区键(UserId)。这对您的查询非常有用。这意味着它只会命中一个分区。根据您的使用情况(以及条目的大小),甚至可以加载整个分区并过滤客户端/应用程序端。当然,这取决于预期的朋友列表大小,以及您需要/愿意做的网络流量与应用处理的数据大小。例如,加载100个条目并过滤接受的应用程序端,并通过过滤数据库端加载50个条目可能具有相似的性能数字。
答案 1 :(得分:2)
这将为查询提供最佳性能: SELECT * FROM friend_list WHERE userId =“---”AND accepted = true;
架构(A)将为您提供更好的查询性能。
我需要对它进行不必要的排序,因为我必须将'ts_accepted'排序到DESC
如果首先按“已接受”排序的结果顺序不会影响您的代码逻辑(记录顺序正确则无需创建索引)
架构问题(B)
在接受时创建索引将创建一个隐藏的列族,其格式为
CREATE TABLE friend_list_accept_idx (
accepted boolean,
userId uuid,
ts_accepted timestamp,
PRIMARY KEY (accepted),userId , ts_accepted)
);
这是您不必要的维护费用。并且总是很好地避免在cassandra中使用索引。