没有WHERE的SELECT的CQL设计

时间:2014-06-21 13:12:29

标签: database-design cassandra cql zebus nosql

我们目前正在重写我们的点对点服务总线目录(Zebus)。

我们有一个Cassandra / Thrift实现,必须对其进行改进以满足一些新的加载要求,因此使用CQL重写它似乎是正确的做法。

我们有两个CF,一个用于存储Peers,一个用于存储Subscriptions,后者是最棘手的。

我们需要为每种消息类型存储路由密钥(绑定)列表,以及每个对等体的消息类型列表。我们还需要能够单独更新每个消息类型的路由列表(我们使用Cassandra的时间戳来处理潜在的竞争条件,因为我们有多个目录)。最后,当有人请求Peers状态时,我们需要能够列出所有这些订阅。

最后一点是一个问题,因为它意味着运行SELECT * FROM "Subscriptions",这意味着列出来自多个节点的行(BTW如何让CQL允许您列出底层的Cassandra行?)并且恰好很慢。 / p>

因此,我们最终为CF提供了以下模式,将所有内容连续存储在同一个Cassandra行的磁盘上并具有良好的读取性能(我们意识到这在平衡节点之间的数据方面非常糟糕)。

CREATE TABLE IF NOT EXISTS "DynamicSubscriptions" (
    "UselessKey" boolean,
    "PeerId" text,
    "MessageTypeId" text,   
    "SubscriptionBindings" blob,
    PRIMARY KEY("UselessKey", "PeerId", "MessageTypeId")
);

这很丑陋但是诀窍,每个人都在同一个“Thrift行”上,导致闪电般快速读取。

所以我的问题如下:如果我希望在无约束的SELECT期间我的数据能够快速查询,是否有漂亮方法来设计使用CQL的CF?

(或者,如果您认为我们的设计存在完全缺陷,请随时说出来。)

2 个答案:

答案 0 :(得分:0)

所以,据我所知,你应该创建这样的表: CREATE TABLE IF NOT EXISTS dynamic_subscriptions ( peer_id text, message_type text, bindings blob, PRIMARY KEY (peer_id, message_type) ); 它与您的非常相似,但主要区别在于主键定义。 主键的第一列是分区键,这意味着具有相同分区键的所有数据将存储在同一物理列族行中。其余主键组件是群集列,用于区分单个分区键中的数据并对其进行排序。

换句话说,这种模式的优点是:

  • 对等数据在群集上均匀分布
  • 您可以有效地查询对等数据(消息类型,带有绑定的消息类型),因为它们被排序并存储在单个节点上
  • 您可以在特定对等方的上下文中有效地查询单个消息类型
  • 您可以在特定对等方的上下文中有效地更新/删除所选消息类型的绑定

我希望这会对你有所帮助。

答案 1 :(得分:0)

通常会有一种方法来限制由用户交互驱动的要被阅读的信息。这也将推动您的数据模型设计。

我可以考虑限制您列出订阅的对等方数量的一种方法是基于时间段。请注意,这需要与您查询以获取每个对等方信息的CF分开。黄金法则是一个CF驱动一个查询。

假设您可以按时间限制向用户显示的对等方数量,下一个要解决的问题是将数据分布在多个分区(Thrift行)中。您可以使用MessageType和时间组件(如日期)的组合作为分区键。当您向用户显示此数据时,您将拥有自然的分页机制。

总结一下,你需要Jacek L提到的CF.此外,为了显示多个同伴的信息,您可以使用类似这样的内容

CREATE TABLE IF NOT EXISTS peer_subscriptions (
    message_type   text,
    connection_date  text,
    peer_id   text,
    bindings  blob,
    PRIMARY KEY ((message_type,connection_date),peer_id)
);