编辑*感谢代码格式化的陌生人,我会记住以后!
我遵循基本的planetcassandra.org Cassandra教程,我不明白为什么我不能执行以下查询:
select *
from users
where lastname = 'Smith' AND city = 'X';
在这张桌子上:
CREATE TABLE users
(
firstname text,
lastname text,
age int,
email text,
city text,
PRIMARY KEY (lastname)
);
根据我的理解,分区键(lastname)对数据进行分区。所以带有姓氏Smith的所有行都应该在节点X上。什么阻止我进一步过滤这些行呢?
谢谢!
答案 0 :(得分:6)
这里有两个问题的答案。一个特定于你的例子,一个更一般的答案(这可能是你真正想要的)。
回答您的例子
在您的具体示例中,您只有一个主键"姓氏"。因此,在这种情况下,每个分区只有一行。任何时候你用姓氏更新行#34;史密斯"您正在覆盖该行中的所有先前数据。在这种情况下,where子句并不真正有意义,因为当你查询" Smith"排在那里只会有一个结果。
更一般的回答
我猜你的意思是允许每个分区允许多行。也许类似于PRIMARY KEY(lastname,user_id)(或聚类键中的任何列,可以让您识别具有相同姓氏的不同用户)。
Cassandra的分区可能非常大。单个分区中可能有数百万行。主键中的群集列确定存储在磁盘上时这些行的排序方式。因此,当您对聚类列进行查询时,Cassandra可以使用数据排序的知识来精确查找您要查找的数据。
如果Cassandra允许查询不在群集密钥中的列,则需要扫描分区中的所有数据并根据查询检查每一行。这将是非常低效的。
要进一步扩展群集列,群集列的实际顺序也很重要。如上所述,排序决定了行存储在磁盘上的方式。所以" PRIMARY KEY(a,b,c)"和" PRIMARY KEY(a,c,b)"是不相同。在第一个示例中,行首先由" b"在磁盘上排序。列,然后是" b"的所有具有相同值的行列由" c"柱。这意味着您无法在分区内查询具有特定值的列" c"没有指定" b"。该查询将再次需要扫描整个分区,因为行首先由" b"排序。
了解您要预先做的确切查询将帮助您确定所需的群集密钥,以及是否需要将多个表格反规范化以支持多个查询。
答案 1 :(得分:3)
您必须拥有一个聚类列 - 城市。
更新:为简洁的回复道歉。让我充实一点。
Cassandra是一款专为高性能和可用性而设计的分布式系统。尽管基于SQL,但CQL在您可以做和不能做的查询类型中受到限制,并且通常您必须围绕您的工作负载/访问模式围绕查询模式(和重复数据)设计数据模型。
确实,一旦在cql where子句中指定了分区键,cassandra就会知道您的数据存储在哪个节点。但是,它仍然必须在该节点中找到数据。
请记住,C *会根据群集列顺序存储数据。为了找到你正在寻找的CQL行,cassandra必须在磁盘上进行完全搜索,一旦你售罄并且拥有大量数据,它们就会很慢。如果您具有聚类列x,y和z,则数据将分别按三个聚类列进行排序。这就是为什么你只能按顺序包含x,y和z约束的原因。
查看this data modeling tool可视化c *存储层的数据模型,查看可能的查询,并生成压力模型。