Cassandra在聚类列排序与二级索引上的性能

时间:2015-08-17 09:53:14

标签: cassandra cassandra-2.0 query-performance nosql

我的架构是:

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中的二级索引。我知道二级索引对于低基数值(布尔值)并不坏。但是查询可能仍有一些性能问题。

请告诉我实现此查询的有效方法。

2 个答案:

答案 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中使用索引。