Database design 有序范围查询的Cassandra数据模型

Database design 有序范围查询的Cassandra数据模型,database-design,cassandra,cassandra-2.0,Database Design,Cassandra,Cassandra 2.0,我正在努力为Cassandra列族/表制定正确的数据模型,这将使我能够查询我需要的内容 我只需要存储表示金融交易的单一类型实体的数据。主要字段(适用于查询、排序): uuid:每个事务的唯一ID 时间戳:事务的时间 source_id:string(基数较低,整个数据集的唯一值通常小于10) destination_id:string(基数较低,整个数据集的唯一值通常小于10) 商户id:字符串(高基数,~100k唯一值) 还有其他字段(总共约20个),但查询或订购时不需要这些字段 我需要通过以

我正在努力为Cassandra列族/表制定正确的数据模型,这将使我能够查询我需要的内容

我只需要存储表示金融交易的单一类型实体的数据。主要字段(适用于查询、排序):

  • uuid:每个事务的唯一ID
  • 时间戳:事务的时间
  • source_id:string(基数较低,整个数据集的唯一值通常小于10)
  • destination_id:string(基数较低,整个数据集的唯一值通常小于10)
  • 商户id:字符串(高基数,~100k唯一值)
  • 还有其他字段(总共约20个),但查询或订购时不需要这些字段

    我需要通过以下两种方式查询交易:

  • 通过UUID
  • 按日期范围,按商户id订购源id/目的地id的准确值
  • UUID查询需要快速,虽然日期范围查询应该尽可能高效,但它每天都作为脱机进程运行,因此可能需要更长的时间。最好了解查询时间在没有记录的情况下是如何伸缩的

    Cassandra将被设置为4个节点的集群,跨越2个数据中心,以防影响分区密钥配置。我用的是卡桑德拉2.0

    作为Cassandra的新手,我一直在阅读关于复合键、timeuuid、切片查询等的内容,但有点困惑。如果有人能提出正确的方法,或者给我指出正确的方向,我将非常感激


    谢谢。

    查询1相当简单,在CQL3中,它看起来像:

    create table tx_by_uuid (
    tx_id uuid PRIMARY KEY,
    tx_time timestamp,
    source_id text,
    dest_id text,
    merchant_id text
    ) 
    
    查询2有点复杂: (注意,我在这里假设source\u id/destination\u id指的是两者都指定的需求,而不是和/或情况)

    由于我们希望通过源\ id/目标\ id的精确值进行查询,因此理想情况下,我们需要使用这些列的组合作为分区键的主键。由于这些是低基数列,我们可能会遇到块状分区的问题,但由于您给了我们一些关于节点数量的额外信息,我们可以通过观察如果这些列中的每一列都有大约10个不同的值,从而确信source_id+destination_id是此表的可接受分区键,当组合起来时,将有大约100个不同的值。在一个更大的集群中,这不是理想的数据分布,我们可能希望在分区键中添加一个临时存储桶,但对于一个四节点集群,我们可能在这里就可以了

    由于我们还希望按数据范围进行查询,因此我们希望将tx_time列作为集群列。此外,由于我们希望看到商家订购的结果,因此还需要一个集群列。最后,为了确保主键唯一地标识各个事务,tx_id应该是最后一个集群列。因此,查询2的表可能如下所示:

    create table tx_by_merchant(
    tx_id uuid,
    tx_time timestamp,
    source_id text,
    dest_id text,
    merchant_id text,
    primary key((source_id, dest_id), tx_time, merchant_id, tx_id)
    )
    
    请注意,这些分区可能非常宽,因此最好在分区键中添加一个年+月补充列,以稍微分解这些分区。此外,如果需要反转顺序,请查看WITH CLUSTERING ORDER子句


    检索由单个主键唯一标识的行的查询速度非常快。从非常宽的分区获取的查询可能会稍微慢一些,但仍然比使用辅助索引完成同样的任务要快。

    非常感谢您的回答。看到您建议的支持范围查询的主键对我很有帮助。我之前尝试过在分区键中使用时间戳,这给了我一个错误。正如我现在所理解的,我必须约束分区键才能查询一个范围,即只查询一个节点?另外,如果我理解正确,您的示例要求在两个表之间复制记录?是否有任何方法可以通过UUID通过一个表高效地访问记录?我假设UUID上的二级索引不是一个好主意,因为基数很高?在Cassandra中,将数据复制到不同的结构中以实现高效查询正是我们的工作方式;)关于高基数,你是完全正确的。谢谢你的澄清。关于我要求查询日期范围内的记录的另一个问题,但按商户ID的订单结果-对于具有相同发送时间值的记录,您建议仅按商户ID的订单的主键。换句话说,如果我查询tx_by_merchant的日期范围,我确实会得到tx_time订购的记录。这是我按日期查询并将结果放入临时表的最佳方法,我可以在merchant_id(使用固定分区键)上对其进行索引?哦,明白了。然后问题就变成了,您认为总共有多少行与这个查询匹配?如果是一吨,您真的希望在一个查询中返回所有这些吗?我认为最好的选择是创建10分钟(或1分钟或1小时)的事务桶。bucket随后成为分区密钥的一部分,您可以获得所需的商户订单。折衷是,要在多个存储桶中查询一个时间范围,您必须发出多个查询。让我知道哪个选项听起来很吸引人,我会编辑答案来展示如何做。谢谢你的跟进。我实现的解决方案是使用一个额外的表来按商户id订购(总共3个表)。我将日期范围查询的结果插入到这个表中(对所有结果使用新的UUID分区键),并通过查询按商户id排序。