【问题标题】:Data Modeling for range queries in CassandraCassandra 中范围查询的数据建模
【发布时间】:2021-11-19 04:42:19
【问题描述】:

我正在 Cassandra 中设计一个新表

创建表学生( studentid 文本主键, 部门文本, 主要文字, 已更新时间戳)

我需要在这个表上执行三个查询

  1. 查询所有数据(findByAll)
  2. 根据专业查询所有数据,计划在此列添加二级索引
  3. 根据时间范围查询数据,即按列更新

我可以使用复合主键来实现这一点,但我也希望行仅基于 id 是唯一可识别的。例如:

第 1 行: 1|工程|电气 | 01-01-2021

如果学生选择不同的专业?

1|工程|机械 | 02-02-2021

我想执行一个 upsert,其中只有专业和更新的列会发生变化。

我的难题是,如果我想对 updatedon 执行范围查询(其中行仅由 id 唯一标识),我不明白我应该将什么作为主键。

我遇到了一种分桶方法,但不确定这是否会给我的简单/最小设计增加额外的复杂性。

【问题讨论】:

    标签: cassandra data-modeling spring-data-cassandra


    【解决方案1】:

    从表格设计开始,您似乎正在倒退。在 Cassandra 中对数据建模时,这听起来违反直觉,但您需要先从应用程序查询开始,然后针对这些查询设计表。

    让我通过列出您的所有应用查询并为每个查询设计一个表格来进行说明。

    APP QUERY 1 - 查询所有数据(findByAll)

    如果您打算检索所有记录以显示它们,那么这在 Cassandra 中是个坏主意,因为它需要进行全表扫描。我知道开发人员习惯于在具有少量数据的玩具应用程序上执行此操作,但在 Cassandra 中,数据分布在节点之间,因此全表扫描无法扩展。

    考虑一下集群中包含数百个节点的百万或更多记录的情况。应用程序等待查询完成检索所有记录是没有意义的。

    APP QUERY 2 - 根据专业查询所有数据,计划在此列添加二级索引

    如果性能对您很重要,那么在 major 上添加索引并不是一个好主意。您应该设计一个专门为此查询优化的表。例如:

    CREATE TABLE students_by_major (
        major text,
        studentid text,
        department text,
        updatedon timestamp,
        PRIMARY KEY (major, studentid)
    )
    

    在此表中,每个major 分区都有1 行或多行studentid。例如:

     major                  | studentid | department  | updatedon
    ------------------------+-----------+-------------+---------------------------------
           computer science |       321 |     science | 2020-01-23 00:00:00.000000+0000
     electrical engineering |       321 | engineering | 2020-02-24 00:00:00.000000+0000
     electrical engineering |       654 | engineering | 2019-05-06 00:00:00.000000+0000
       chemical engineering |       654 | engineering | 2019-07-08 00:00:00.000000+0000
                       arts |       987 |         law | 2020-09-12 00:00:00.000000+0000
          civil engineering |       654 | engineering | 2019-02-04 00:00:00.000000+0000
    

    APP QUERY 3 - 根据时间范围查询数据,即按列更新

    如果列在主键中定义,您将只能对 updatedon 执行范围查询。

    APP QUERY 4 - 如果学生要选择不同的专业?

    您可以有一个表格,其中每个学生都有多行专业:

    CREATE TABLE majors_by_student (
        studentid text,
        major text,
        department text,
        updatedon timestamp,
        PRIMARY KEY (studentid, major)
    )
    

    例如,学生ID654已更新专业3次:

    cqlsh> SELECT * FROM majors_by_student WHERE studentid = '654';
    
     studentid | updatedon                       | department  | major
    -----------+---------------------------------+-------------+------------------------
           654 | 2019-07-08 00:00:00.000000+0000 | engineering |   chemical engineering
           654 | 2019-05-06 00:00:00.000000+0000 | engineering | electrical engineering
           654 | 2019-02-04 00:00:00.000000+0000 | engineering |      civil engineering
    

    QUERY 5 - 您希望对 updatedon 执行范围查询,其中行仅由 studentid 唯一标识。

    CREATE TABLE community.updated_majors_by_student (
        studentid text,
        updatedon timestamp,
        department text,
        major text,
        PRIMARY KEY (studentid, updatedon)
    )
    

    以上面的学生654 为例,您可以对 4 月 30 日之后的任何更新进行范围查询:

    SELECT * FROM updated_majors_by_student WHERE studentid = '654' AND updatedon > '2019-04-30 +0000';
    

    请注意,由于updatedon 是时间戳,因此您需要指定精确时区,+0000 是 UTC 的 TZ。

     studentid | updatedon                       | department  | major
    -----------+---------------------------------+-------------+------------------------
           654 | 2019-07-08 00:00:00.000000+0000 | engineering |   chemical engineering
           654 | 2019-05-06 00:00:00.000000+0000 | engineering | electrical engineering
    

    要保持上述表格同步,您需要使用我在本文中描述的 CQL BATCH 语句 -- https://community.datastax.com/articles/2744/。干杯!

    【讨论】:

      猜你喜欢
      • 2014-03-04
      • 1970-01-01
      • 2018-01-15
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 2016-08-20
      • 2015-03-10
      相关资源
      最近更新 更多