如何在cassandra中进行有序选择?

时间:2015-08-03 11:53:59

标签: cassandra cql

我有一张这样的表:

CREATE TABLE test ( 
    uid uuid,
    rec int,
    Primary key (uid, rec)
) WITH CLUSTERING ORDER BY (rec DESC ) ;

我想从某个uid开始获取记录并限制100,但cassandra不允许这样的请求:

SELECT * FROM test WHERE uid > ee0f57b0-255c-11e5-9f08-8f9ef2abcffc LIMIT 100

请求:

SELECT * FROM test

输出随机排序的所有记录。

2 个答案:

答案 0 :(得分:3)

如果要在CQL中执行范围查询,则需要将记录放在同一分区中。因此,如果要对uid执行范围查询,则需要使用群集列而不是分区键。数据按簇聚类排序,而不是按分区键排序。

但是对于uuid进行范围查询没有多大意义,因为它们通常被认为是随机数而不是有序数。如果您使用了timeuuid,那么它们将按创建时间排序。

如果您正在尝试读取uuid的范围以便可以处理数据块,那么您可以使uuid成为一个聚类列,并为块号提供一个分区键。

答案 1 :(得分:2)

Cassandra不允许对分区键进行范围查询。正如Jim所说,您需要创建一个包含不同分区键的表,并将您的范围应用于聚类列。

  

输出随机排序的所有记录。

不正确的。虽然从没有SELECT子句的CQL WHERE返回的结果可能看起来是随机排序的,但它们将按照从磁盘读取的顺序返回给您。使用token函数时可以看到这一点:

aploetz@cqlsh:stackoverflow2> SELECT uid, token(uid), rec FROM testrangeordering ;

 uid                                  | system.token(uid)    | rec
--------------------------------------+----------------------+-----
 559f31f1-04a5-4a65-959e-866b19f671e8 | -4639349469716736139 |   4
 559f31f1-04a5-4a65-959e-866b19f671e8 | -4639349469716736139 |   3
 559f31f1-04a5-4a65-959e-866b19f671e8 | -4639349469716736139 |   2
 559f31f1-04a5-4a65-959e-866b19f671e8 | -4639349469716736139 |   1
 c9cbd305-649f-4f6f-9c8a-1ebc4192def4 | -1664662098145733545 |   4
 c9cbd305-649f-4f6f-9c8a-1ebc4192def4 | -1664662098145733545 |   3
 c9cbd305-649f-4f6f-9c8a-1ebc4192def4 | -1664662098145733545 |   2
 c9cbd305-649f-4f6f-9c8a-1ebc4192def4 | -1664662098145733545 |   1
 4c0b5615-3782-411c-9791-7c2dfae4533c | -1466462644843772696 |   1

(9 rows)

如您所见,您的结果按其分区键(uid)的哈希标记值排序,并且您指定的排序在每个分区中反映

并且回应Jim所说的(再次)范围查询使得timeuuid更有意义。要修复分区密钥问题,您可能需要考虑使用“存储桶”。假设我使用timeuuid作为第一个聚类键重新创建表,并将当前年份的时间段作为分区键重新创建:

CREATE TABLE testRangeOrderingByTime ( 
    bucket text,
    time timeuuid,
    rec int,
    Primary key (bucket, time, rec)
) WITH CLUSTERING ORDER BY (time DESC, rec DESC) ;

现在我可以稍微修改一下你的范围查询(上面)(在我的bucket子句中将WHERE限制为'2015'):

aploetz@cqlsh:stackoverflow2> SELECT dateof(time), time, rec 
    FROm testrangeorderingbytime WHERE bucket='2015'
    AND time > ee0f57b0-255c-11e5-9f08-8f9ef2abcffc;

 system.dateof(time)      | time                                 | rec
--------------------------+--------------------------------------+-----
 2015-08-03 11:08:16-0500 | d9c51540-39f9-11e5-93d6-21b264d4c94d |   3
 2015-08-03 11:08:16-0500 | d9c403d0-39f9-11e5-93d6-21b264d4c94d |   3
 2015-08-03 11:08:16-0500 | d9c31970-39f9-11e5-93d6-21b264d4c94d |   3
 2015-08-03 11:07:43-0500 | c608e5e0-39f9-11e5-93d6-21b264d4c94d |   2
 2015-08-03 11:07:43-0500 | c6078650-39f9-11e5-93d6-21b264d4c94d |   2
 2015-08-03 11:07:43-0500 | c603dcd0-39f9-11e5-93d6-21b264d4c94d |   2
 2015-08-03 11:07:16-0500 | b5c95a20-39f9-11e5-93d6-21b264d4c94d |   1
 2015-08-03 11:07:16-0500 | b5c821a0-39f9-11e5-93d6-21b264d4c94d |   1
 2015-08-03 11:07:16-0500 | b5c625d0-39f9-11e5-93d6-21b264d4c94d |   1

(9 rows)

为了进一步参考,我去年在PlanetCassandraWe Shall Have Order!)上写了一篇讨论这个主题的文章,这可能对你有帮助。另外,Patrick McFadin关于Getting Started With Time Series Data Modeling的文章也很适合这个主题。