【问题标题】:Cassandra partitioning of composite keys复合键的 Cassandra 分区
【发布时间】:2015-07-22 19:02:10
【问题描述】:

据我了解,如果我们有一个主键,则该键用于对数据进行分区并将其存储在节点中(例如使用随机分区器)。

现在我不确定的是,如果我有多个 keys(又名复合键),是用于对数据进行分区的键组合还是第一个主键?

例如,对于单个键列族,例如:

CREATE TABLE IF NOT EXISTS users (
    userid uuid,
    emailaddress text,
    birthday timestamp,
    PRIMARY KEY (userid)
);

我知道userid 用于确定应将users 类型的行分区到哪个节点。

如果我将此表更改为

CREATE TABLE IF NOT EXISTS users (
    userid uuid,
    emailaddress text,
    birthday timestamp,
    PRIMARY KEY (userid, emailaddress)
);

这是否意味着现在useridemailaddress 将一起使用以确定分区?

是否可以将具有相同userid 但不同emailaddress 的两行分配到两个单独的节点中,或者它们总是位于同一个节点中?

非常感谢,

【问题讨论】:

    标签: cassandra cassandra-2.0


    【解决方案1】:

    事实上在你的例子中

    CREATE TABLE IF NOT EXISTS users (
        userid uuid,
        emailaddress text,
        birthday timestamp,
        PRIMARY KEY (userid, emailaddress)
    );
    

    userid 是分区键部分,emailaddress 是集群列,在 cqlsh 中

    cqlsh:rw> CREATE TABLE users ( userid INT, email TEXT, data TEXT, PRIMARY KEY ( userid, email ) );
    cqlsh:rw> SELECT * FROM users WHERE userid = 0;
    
     userid | email | data       
    

    分区键部分由内大括号()定义

    CREATE TABLE IF NOT EXISTS users (
        userid uuid,
        emailaddress text,
        birthday timestamp,
        PRIMARY KEY ((userid, emailaddress))
    );
    

    现在您将拥有由用户 ID 和电子邮件地址组成的分区键,并再次在 cqlsh 中

    cqlsh:rw> CREATE TABLE users ( userid INT, email TEXT, data TEXT, PRIMARY KEY ( ( userid, email ) ) );                                                                                                                                                                     
    cqlsh:rw> SELECT * FROM users WHERE userid = 0;
    code=2200 [Invalid query] message="Partition key part email must be restricted since preceding part is"     
    

    现在回答你的问题 -> 是的,因为你只有复合键分区键部分作为用户 ID。

    有趣的信息来源: http://docs.datastax.com/en/cql/3.1/cql/cql_reference/refCompositePk.html

    尝试的好工具是 cqlsh - 它可以帮助您测试很多东西。例如,在 cqlsh 输出分区键列是红色,集群列青色/蓝色和数据列紫罗兰色 - 非常有帮助

    更新评论 继续第二种情况,查询

    cqlsh:rw> SELECT * FROM users WHERE userid = 0 AND email = '';
    
     userid | email | data
    --------+-------+------
    

    将成功,因此您必须始终指定用户 ID 和电子邮件

    要查询一个用户和您可以使用的多个电子邮件地址

    SELECT * FROM users WHERE userid = 0 AND email IN ( 'a', '4' );
    
     userid | email | data
    --------+-------+------
    

    但是 IN 子句很昂贵,因为这意味着联系节点必须连接许多节点来收集数据,所以最好使用并行查询,但您还必须指定电子邮件值。第二种情况的第一次选择以错误结束。但是,从示例中,一个用户可以有很多电子邮件,所以第一种情况应该足够了 - 取决于 db 的期望。在第二种情况下,如果没有电子邮件字段,它将无法工作。

    第一种情况

    CREATE TABLE users ( userid INT, email TEXT, data TEXT, PRIMARY KEY ( userid, email ) );
    INSERT INTO users (userid, email , data ) VALUES( 0, 'email@a.pl', 'ddd');
    INSERT INTO users (userid, email , data ) VALUES( 0, 'email1@a.pl', 'ddd1111');
    

    您将插入一些按电子邮件地址聚类的数据,因此您将与一个用户建立关系 -> 电子邮件中的许多数据至少您在评论中的问题表明了这一点。这是结果

    cqlsh:rw> SELECT * FROM users WHERE userid = 0;
    
     userid | email       | data
    --------+-------------+---------
          0 | email1@a.pl | ddd1111
          0 |  email@a.pl |     ddd
    

    【讨论】:

    • 非常感谢您。不过我还有一个问题。如果我按照您的方式进行操作,即将((userid, emailaddress)) 作为我的分区键,我是否仍然可以仅通过用户 ID 进行搜索而不指定电子邮件地址?以我的示例为例,我可以,但是如果它们都是分区键,我不确定是否可以做到。
    • @kha 这种情况你必须使用允许过滤
    猜你喜欢
    • 2014-09-23
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 2014-06-10
    • 2016-03-22
    • 1970-01-01
    • 2015-03-24
    • 2012-12-05
    相关资源
    最近更新 更多