复合键的 Cassandra 分区
Cassandra partitioning of composite keys
据我了解,如果我们有一个主键,则使用此键对数据进行分区并将其存储在节点中(例如使用随机分区程序)。
现在我不确定的是,如果我有多个 keys
(又名复合键),是用于分区数据的键的组合还是它将成为第一个主键钥匙?
例如,对于单个键列族,例如:
CREATE TABLE IF NOT EXISTS users (
userid uuid,
emailaddress text,
birthday timestamp,
PRIMARY KEY (userid)
);
我知道 userid
用于确定应将 users
类型的行分区到哪个节点。
如果我将此 table 更改为
CREATE TABLE IF NOT EXISTS users (
userid uuid,
emailaddress text,
birthday timestamp,
PRIMARY KEY (userid, emailaddress)
);
这是否意味着现在userid
和emailaddress
要一起使用以确定分区?
是否可以将具有相同 userid
但不同 emailaddress
的两行分配到两个单独的节点中,或者它们是否始终位于同一节点中?
非常感谢,
事实上在你的例子中
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))
);
现在您将在 cqlsh 中再次拥有由用户 ID 和电子邮件地址组成的分区键
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"
现在回答你的问题 -> 是的,这是可能的,因为你的复合键分区键部分仅作为用户标识。
有趣的信息来源:
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 子句很昂贵,因为这意味着联系节点必须连接许多节点以收集数据,因此最好使用并行查询,但您还必须指定电子邮件值。第二种情况的第一个 select 以错误结束。但是,从示例来看,一个用户可以有很多电子邮件,因此第一种情况应该足够了——取决于 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
据我了解,如果我们有一个主键,则使用此键对数据进行分区并将其存储在节点中(例如使用随机分区程序)。
现在我不确定的是,如果我有多个 keys
(又名复合键),是用于分区数据的键的组合还是它将成为第一个主键钥匙?
例如,对于单个键列族,例如:
CREATE TABLE IF NOT EXISTS users (
userid uuid,
emailaddress text,
birthday timestamp,
PRIMARY KEY (userid)
);
我知道 userid
用于确定应将 users
类型的行分区到哪个节点。
如果我将此 table 更改为
CREATE TABLE IF NOT EXISTS users (
userid uuid,
emailaddress text,
birthday timestamp,
PRIMARY KEY (userid, emailaddress)
);
这是否意味着现在userid
和emailaddress
要一起使用以确定分区?
是否可以将具有相同 userid
但不同 emailaddress
的两行分配到两个单独的节点中,或者它们是否始终位于同一节点中?
非常感谢,
事实上在你的例子中
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))
);
现在您将在 cqlsh 中再次拥有由用户 ID 和电子邮件地址组成的分区键
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"
现在回答你的问题 -> 是的,这是可能的,因为你的复合键分区键部分仅作为用户标识。
有趣的信息来源: 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 子句很昂贵,因为这意味着联系节点必须连接许多节点以收集数据,因此最好使用并行查询,但您还必须指定电子邮件值。第二种情况的第一个 select 以错误结束。但是,从示例来看,一个用户可以有很多电子邮件,因此第一种情况应该足够了——取决于 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