如何在 cassandra 中制作有序的 select?

How to make ordered select in the cassandra?

我有一个 table 这样的:

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

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

如果要在CQL 中进行范围查询,则需要将记录放在同一分区中。所以如果你想对 uid 进行范围查询,它需要是一个聚类列而不是分区键。并且数据按聚簇列排序,而不是按分区键排序。

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

如果您尝试读取 uuid 的范围以便您可以分块处理数据,那么您可以将 uuid 设为聚簇列并为块编号设置分区键。

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

outputs all records random ordered.

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

aploetz@cqlsh:Whosebug2> 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 进行范围查询更有意义。要解决您的分区键问题,您可能需要考虑使用 "bucket." 假设我使用 timeuuid 作为第一个聚类键,并将当年的时间段作为分区来重新创建您的 table键:

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

现在我可以 运行 您的范围查询(上图)稍作修改(在我的 WHERE 子句中将 bucket 限制为“2015”):

aploetz@cqlsh:Whosebug2> 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)

为了进一步参考,我在 PlanetCassandra last year (We Shall Have Order!), which might help you. Also, Patrick McFadin's article on Getting Started With Time Series Data Modeling 上写了一篇讨论该主题的文章,这也是该主题的好读物。