为什么我不能在过滤主键后在Cassandra中添加WHERE子句?

时间:2015-04-17 18:23:37

标签: cassandra datastax nosql

编辑*感谢代码格式化的陌生人,我会记住以后!

我遵循基本的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上。什么阻止我进一步过滤这些行呢?

谢谢!

2 个答案:

答案 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将数据按顺序存储在磁盘上(快速浏览C *读取路径)

Cassandra是一款专为高性能和可用性而设计的分布式系统。尽管基于SQL,但CQL在您可以做和不能做的查询类型中受到限制,并且通常您必须围绕您的工作负载/访问模式围绕查询模式(和重复数据)设计数据模型。

确实,一旦在cql where子句中指定了分区键,cassandra就会知道您的数据存储在哪个节点。但是,它仍然必须在该节点中找到数据。

请记住,C *会根据群集列顺序存储数据。为了找到你正在寻找的CQL行,cassandra必须在磁盘上进行完全搜索,一旦你售罄并且拥有大量数据,它们就会很慢。如果您具有聚类列x,y和z,则数据将分别按三个聚类列进行排序。这就是为什么你只能按顺序包含x,y和z约束的原因。

查看this data modeling tool可视化c *存储层的数据模型,查看可能的查询,并生成压力模型。