Cassandra CQL中的Where和Order By子句

时间:2016-02-29 19:38:14

标签: cassandra cql cql3

我是NoSQL数据库的新手,刚刚开始使用apache Cassandra。我在“empno”列上创建了一个带有主键的简单表“emp”。这是一个简单的表,因为我们总是使用Oracle的默认scott模式。

现在我使用COPY命令加载了数据并发出了查询Select * from emp order by empno,但我很惊讶CQL不允许empno列上的Order by(这是PK)。此外,当我使用Where条件时,它不允许对empno列进行任何不等式操作(它表示只允许EQ或IN条件)。它也不允许任何其他列的Where和Order by,因为它们没有在PK中使用,也没有索引。

有人可以帮助我,如果我想在表格中保持empno唯一,并希望查询结果按empno的排序顺序,我该怎么办?

(我的版本是:

cqlsh:demodb> show version [cqlsh 5.0.1 | Cassandra 2.2.0 | CQL spec 3.3.0 | Native protocol v4]

2 个答案:

答案 0 :(得分:17)

Cassandra的PRIMARY KEY有两个部分:

  • 分区键
  • 群集密钥

PRIMARY KEY (partitionKey1,clusteringKey1,clusteringKey2)

PRIMARY KEY ((partitionKey1,partitionKey2),clusteringKey1,clusteringKey2)

分区键确定您的数据存储在哪个节点上。群集键确定分区键中数据的顺序。

在CQL中,ORDER BY子句实际上仅用于反向聚类顺序的已定义排序方向。至于列本身,您只能在创建表时指定CLUSTERING ORDER BY子句中定义的列(并按照确切的顺序...不跳过)。因此,您无法选择任意列来在查询时对结果集进行排序。

Cassandra通过使用群集密钥对磁盘上的数据进行排序来实现性能,从而仅在一次读取中返回有序行(无随机读取)。这就是您必须使用Cassandra采用基于查询的建模方法(通常将数据复制到多个查询表中)的原因。提前了解您的问题,并构建表格以便为其提供服务。

Select * from emp order by empno;

首先,您需要一个WHERE子句。没有它可以查询,如果您正在使用关系数据库。使用Cassandra,您应该尽力避免未绑定的SELECT查询。此外,Cassandra只能在分区中强制执行排序顺序,因此在没有WHERE子句的情况下查询不会以您想要的顺序返回数据。

其次,正如我上面提到的,您需要定义群集密钥。如果您想按empno订购结果集,则必须找到另一列来定义您的分区键。尝试这样的事情:

CREATE TABLE emp_by_dept (
  empno text,
  dept text,
  name text,
  PRIMARY KEY (dept,empno)
) WITH CLUSTERING ORDER BY (empno ASC);

现在,我可以按部门查询员工,他们将按empno命令退回给我:

SELECT * FROM emp_by_dept WHERE dept='IT';

但要明确的是,您能够查询表格中的每一行,并按单列排序。获得有意义的订单到结果集的唯一方法是首先以对业务案例有意义的方式对数据进行分区。运行未绑定的SELECT将返回所有行(假设查询在尝试查询群集中的每个节点时没有超时),但结果集排序只能在分区内强制执行。所以你必须通过分区键来限制,以使其有意义。

我为自我推销道歉,但去年我写了一篇名为We Shall Have Order!的DataStax文章,其中我解决了如何解决这些类型的问题。给它一个阅读,看看它是否有帮助。

修改其他问题:

  

根据你的回答,我总结了两件关于卡桑德拉的事情:

     

(1)没有   获取结果集的方法,该结果集仅由具有的列排序   被定义为唯一。

     

(2)当我们定义PK时   (partition-key + clustering-key),然后结果将始终是order   通过在任何固定分区键中对列进行聚类(我们必须限制   到一个分区键值),这意味着不需要ORDER BY   子句,因为它不能改变行的顺序(顺序)   实际存储了哪些行,即Order By无用。

1)Cassandra中的所有PRIMARY KEY都是独一无二的。您无法通过分区键订购结果集。在我的示例中,我按empno排序(在按部门划分之后)。 - Aaron 1小时前

2)没有说ORDER BY没用,我说它唯一真正的用途就是在ASC和DESC之间切换排序方向。

  

我在" empno"上创建了一个索引。 " emp"表,它仍然没有   允许ORDER BY empno。那么,索引的用途是什么?他们只是为了   搜索索引键特定值的记录?

您无法通过索引列对结果集进行排序。二级索引(与它们的关系对应物不同)实际上仅对边缘案例,基于分析的查询有用。它们不会缩放,因此一般建议不要使用二级索引。

  

好的,这只是意味着一张桌子不能用来获取   具有不同条件和不同排序的不同结果集   顺序。

正确。

  

因此,对于每个新要求,我们需要创建一个新表。   IT意味着如果表中有十亿行(比如Sales表),那么   我们需要销售总额(1)产品方面,(2)区域方面,然后我们将   复制2个表中的所有十亿行,其中一个在聚类中   产品的顺序,另一个是Region的聚类顺序。乃至   如果我们需要按Salesman_id对销售额求和,那么我们构建第3个表,   又把所有那些十亿行?这是明智的吗?

由您来决定它是多么明智,这取决于您。但缺乏查询灵活性是Cassandra的缺点。为了解决这个问题,您可以继续创建查询表(I.E.,交易磁盘以获得性能)。但如果它变得笨拙或难以管理,那么现在是时候考虑一​​下Cassandra是否真的是正确的解决方案。

编辑20160321

  

嗨Aaron,你在上面说过&#34;没有说ORDER BY没用,我说它唯一真正的用途是在ASC和DESC之间切换排序方向。&#34; < / p>      

但我发现即使这是不正确的。 Cassandra只允许ORDER与我们在&#34; CLUSTERING ORDER BY&#34;中定义的方向相同。 CREATE TABLE的caluse。如果在该子句中我们定义了ASC,它只允许ASC订购,反之亦然。

如果没有看到错误消息,很难知道在该消息上告诉您什么。虽然在分区中存储了太多行时,我听说ORDER BY的查询失败了。

如果指定多个列进行排序,

ORDER BY也会有点奇怪。如果我定义了两个聚类列,我可以不加选择地在第一列使用ORDER BY。但是,只要我将第二列添加到ORDER BY子句,只有在指定两个排序方向相同(作为CLUSTERING ORDER BY定义)或两者不同。如果我混合搭配,我明白了:

InvalidRequest: code=2200 [Invalid query] message="Unsupported order by relation"

我认为这与数据如何存储在磁盘上有关。否则,Cassandra在准备结果集方面还有更多工作要做。然而,如果它要求所有内容匹配或镜像CLUSTERING ORDER BY中指定的方向,它只能从磁盘中继顺序读取。因此,最好只在ORDER BY子句中使用单个列,以获得更可预测的结果。

答案 1 :(得分:0)

添加一个redux答案是很长的。

Order by当前仅在PRIMARY KEY的聚集列上受支持 以及当where子句中的分区键受Equality或IN运算符限制时。

也就是说,如果您这样定义主键:

PRIMARY KEY ((a,b),c,d)

然后,当&仅在查询具有以下条件时,您才可以使用ORDER BY:

  

其中所有主键都由相等运算符(=)或IN运算符(例如:

)限制的where子句
SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c,d;

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c;

这两个查询是唯一有效的查询。

此查询也不起作用:

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY d,c;

因为order by当前仅支持在d之前声明主键定义c中的PRIMARY KEY中列的声明顺序之后的列排序,并且查询通过将d放在首位来违反顺序。