能否仅使用复合分区键的一部分查询cassandra表?

能否仅使用复合分区键的一部分查询cassandra表?,cassandra,data-modeling,cql,Cassandra,Data Modeling,Cql,考虑这样一个表来存储用户的联系人- CREATE TABLE contacts { user_name text, contact_name text, contact_id int, contact_data blob, PRIMARYKEY ((user, contact_name), contact_id) // ^-- Note the composite partition key } 复合分区键为每个联系人生成一行

考虑这样一个表来存储用户的联系人-

CREATE TABLE contacts {
    user_name text,
    contact_name text,
    contact_id int, 
    contact_data blob,
    PRIMARYKEY ((user, contact_name), contact_id)
    //          ^-- Note the composite partition key
}
复合分区键为每个联系人生成一行

假设有1亿用户,每个用户都有几百个联系人

我可以使用

SELECT contact_data FROM contacts WHERE user_name='foo' AND contact_name='bar'
但是,是否也可以使用以下内容查找用户的所有联系人姓名:

SELECT contact_name FROM contacts WHERE user_name='foo'
??WHERE子句是否只能包含构成主键的所有列中的一部分

编辑-我试过这个,卡桑德拉不允许。因此,我现在的问题是,如何对数据建模以支持两个查询-

获取特定用户和联系人的数据 获取用户的所有联系人姓名 我可以想出两个选择-

创建另一个包含user_name和contact_name的表,其中只有user_name作为主键。但是,如果一个用户有太多的联系人,这会是一个广泛的争议问题吗? 在用户名上创建索引。但考虑到100万用户,每个用户只有几百个联系人,用户名会被认为是一个很高的基数值,因此不适合在索引中使用吗?
在RDBMS中,查询计划器可能能够为这种查询创建有效的查询计划。但卡桑德拉不能。卡桑德拉必须做一个表格扫描。卡桑德拉尽力不让你做那种查询。因此它应该拒绝它。

您可以使用两个具有相同结构但不具有相同分区键的不同表:

创建表格联系人{ 用户名文本, 联系人姓名文本, 联络(国际), 联系_数据blob, 主键用户名、联系人姓名、联系人id } 按用户创建表格联系人{ 用户名文本, 联系人姓名文本, 联络(国际), 联系_数据blob, 主键用户名、联系人id }

有了这种结构,您就有了数据复制,您必须手动维护这两个表

如果您使用的是cassandra>3.0,还可以使用物化视图:

创建表格联系人{ 用户名文本, 联系人姓名文本, 联络(国际), 联系_数据blob, 主键用户名、联系人姓名、联系人id } 由用户创建物化视图契约 像 挑选* 从合同中 其中用户名不为空 合同名称不为空 并且合同id不为空 主键用户名、合同名、合同id 按合同名称ASC进行聚类排序


在这种情况下,您只需维护表契约,视图将自动更新。不,您不能。如果您了解cassandra存储数据的机制,就会理解为什么不能按部分复合分区键进行查询

Cassandra基于分区密钥跨节点分发数据。写入请求的协调器使用分区键上的3算法生成哈希令牌,并将写入请求发送给令牌的所有者。每个节点都有其拥有的令牌范围。在读取期间,协调器再次基于分区密钥计算哈希令牌,并将读取请求发送到令牌的所有者节点


由于您使用的是复合分区密钥,在写请求期间,密钥user、contact_name的所有组件都将用于生成哈希令牌。此令牌的所有者节点具有整行。在读取请求期间,您必须提供密钥的所有组件来计算令牌,并向该令牌的正确所有者发出读取请求。因此,Cassandra强制您提供整个分区密钥

我只是想核实一下,结果正如你所指出的。我已经编辑了我的问题-你能评论一下我在报告中提到的两个选项吗edit@PuneetArora不,我不会。如果你有一个新问题,问一个新问题。好的,不用担心,我继续单独问:在联系人列表中只有用户名和联系人名称不是更好吗?contacts表的想法是不要在单个分区上存储太多内容。考虑CONTACTY数据是一个巨大的玩笑,你可以,但你必须运行另一个合同的查询,以获得您的合同数据。我看不出一个用户一个用户的联系方式以及你所说的联系方式有什么意义。在这种情况下,联系人没有任何用途,因为我最终会在第一步中获取联系人的数据