【问题标题】:Cassandra Schema DesignCassandra 架构设计
【发布时间】:2012-09-17 11:37:54
【问题描述】:

我正在继续探索 Cassandra,我想创建类似于 RDBMS 上的多对多的学生 课程关系。

在查询方面,我将使用以下查询;

  1. 检索学生注册的所有课程。
  2. 检索所有注册特定课程的学生。

假设我为列族创建。一个用于课程,另一个用于学生。

CREATE COLUMN FAMILY student with comparator = UTF8Type AND key_validation_class=UTF8Type and column_metadata=[ 
{column_name:firstname,validation_class:UTF8Type} 
{column_name:lastname,validation_class:UTF8Type}
{column_name:gender,validation_class:UTF8Type}];


CREATE COLUMN FAMILY course with comparator = UTF8Type AND key_validation_class=UTF8Type and column_metadata=[ 
{column_name:name,validation_class:UTF8Type} 
{column_name:description,validation_class:UTF8Type}
{column_name:lecturer,validation_class:UTF8Type}
{column_name:assistant,validation_class:UTF8Type}];

现在我应该如何继续?

我应该使用courseID:studentId CompisiteKey 创建第三个列族吗?如果是,我可以使用 Hector 仅通过一个(左或右)复合键组件进行查询吗?

请帮忙。

更新:

按照建议,我创建了以下架构:

对于学生:

CREATE COLUMN FAMILY student with comparator = UTF8Type and key_validation_class=UTF8Type and default_validation_class=UTF8Type;

然后我们将添加一些数据:

set student['student.1']['firstName']='Danny'
set student['student.1']['lastName']='Lesnik'
set student['student.1']['course.1']=''
set student['student.1']['course.2']='';

为课程创建列族:

CREATE COLUMN FAMILY course with comparator = UTF8Type and key_validation_class=UTF8Type and default_validation_class=UTF8Type;

添加一些数据:

set course['course.1']['name'] ='History'
set course['course.1']['description'] ='History Course'
set course['course.1']['name'] ='Algebra'
set course['course.1']['description'] ='Algebra Course'

最后是课程中的学生:

CREATE COLUMN FAMILY StudentInCourse with comparator = UTF8Type and key_validation_class=UTF8Type and default_validation_class=UTF8Type;

添加数据:

set StudentInCourse['studentIncourse.1']['student.1'] =''; 
set StudentInCourse['studentIncourse.2']['student.1'] =''; 

【问题讨论】:

    标签: nosql cassandra hector


    【解决方案1】:

    我在下面定义了一个数据模型,但先描述对象模型然后深入研究行模型更容易,所以从 PlayOrm 的角度来看,你会拥有

    public class Student {
      @NoSqlId
      private String id;
      private String firstName;
      private String lastName;
      @ManyToMany
      private List<Course> courses = new ArrayList(); //constructing avoids nullpointers
    }
    
    public class Course {
      @NoSqlId
      private String id;
      private String name;
      private String description
      @ManyToOne
      private Lecturer lecturer;
      @ManyToMany
      private CursorToMany students = new CursorToManyImpl();
    }
    

    我本可以在课程中使用 List,但我担心如果有太多学生多年来学习一门课程,我可能会出现 OutOfMemory。现在,让我们跳到 PlayOrm 所做的事情,如果您愿意,您可以做类似的事情

    单个学生行看起来像这样

    rowKey(the id in above entity) = firstName='dean',
    lastName='hiller' courses.rowkey56=null, courses.78=null, courses.98=null, courses.101=null
    

    这是宽行,我们有许多名为“fieldname”和“rowkey to actual course”的列

    Course 行更有趣....因为用户认为为单个课程加载所有学生可能会导致内存不足,所以他使用一个游标,在您循环时一次只加载 500 个。

    在这种情况下,PlayOrm 将有两行支持 Course。 Sooo,让我们把我们的用户行放在上面,他在课程 rowkey56 所以让我们描述一下那个课程

    rowkey56 = name='coursename', description='somedesc', lecturer='rowkey89ToLecturer'
    

    然后,在一些学生的索引表中还有另一行(这是一个非常宽的行,最多支持数百万学生)

    indexrowForrowkey56InCourse = student34.56, student39.56, student.23.56.... 
    into the millions of students
    

    如果您希望一门课程拥有超过数百万的学生,那么您需要考虑是否使用 playOrm 进行分区。如果您需要,PlayOrm 会为您进行分区。

    注意:如果你不知道 hibernate 或 JPA,当你加载上面的 Student 时,它会加载一个代理列表,所以如果你开始循环访问课程,它会返回 noSQL 存储并加载课程,这样你不必;)。

    在 Course 的情况下,它会加载一个代理 Lecturer,该代理 Lecturer 会在您访问像 leller.getName() 这样的属性字段之前不会被填写。如果您调用讲师.getId(),它不需要加载讲师,因为它已经从课程行中获得。

    编辑(更多细节):PlayOrm 有 3 个索引表 Decimal(存储 double、float 等和 BigDecimal)、Integer(long、short 等以及 BigInteger 和 boolean)和 String 索引表。当您使用 CursorToMany 时,它会根据键的 FK 类型使用这些表之一。它还将这些表用于它的 Scalable-SQL 语言。它在 CursorToMany 上使用单独行的原因只是为了让客户端在读取一行时不会出现 OutOfMemory,因为在某些情况下 toMany 可能有一百万个 FK。 CursorToMany 然后从该索引行中批量读取。

    后来, 院长

    【讨论】:

    • 感谢您的回复。你能看看我的更新。我认为我的架构与您建议的非常相似。如果我错了,请纠正我。
    • 另一个问题。 “某些索引表中的行”是什么意思?你能再解释一下吗?
    • 是的,您可以在更新中执行该模式,或者您可以只使用两个 col 系列并将 tomany 嵌入到学生和课程表的同一行中(但再次取决于您想要什么/需要)。
    猜你喜欢
    • 2011-06-06
    • 2013-05-11
    • 2010-09-28
    • 2011-11-18
    • 2016-06-22
    • 2020-07-24
    • 2012-08-25
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多