1

我在 Scylla(兼容 Cassandra 的数据库)中有一个表,定义如下:

create table s.items (time timeuuid, name text, primary key (time));

我想运行一个查询,在一定时间后获取所有项目,类似于以下内容:

select * from s.items where time>7e204790-43bf-11e9-9759-000000000004 order by time asc;

但有人告诉我,ORDER BY is only supported when the partition key is restricted by an EQ or an IN.要解决这个问题,我可以制作一个类似于以下内容的表格和查询:

create table s.items (yes boolean, time timeuuid, name text, primary key (yes, time));

select * from s.items where yes=true and time>7e204790-43bf-11e9-9759-000000000004 order by time asc;

虽然这可行,但它似乎不是最好的解决方案。由于我对 Scylla 和 CQL 还很陌生,有没有更好/正确的方法来做到这一点?

4

2 回答 2

1

您添加一个布尔键并始终将其设置为 yes 的解决方案基本上会创建一个包含所有数据的巨大分区。这很少是你真正想要的。如果这个分区是您的全部数据,这意味着即使您有一个 10 节点集群,每个节点上有 8 个 CPU,集群中所有 80 个 CPU 中只有 3 个 CPU 会做任何工作(因为每个分区都属于一个某些 CPU,并且 RF=3 有 3 个副本)。

如果您想知道为什么您的原始解决方案不起作用并且 Scylla 拒绝了“ORDER BY”,那么问题是尽管 Scylla 可以扫描整个表以在时间 X 之后查找条目(您需要添加 ' ALLOW FILTERING'),它没有有效的方法来按时间对找到的内容进行排序。在内部,不同的分区不是按分区键排序的,而是按分区键的哈希函数“令牌”排序的。这种具有随机化效果的散列对于平衡集群上所有 CPU 之间的负载很重要,但会阻止 Scylla(或 Cassandra)以原始密钥顺序读取分区。

您可以做的一件事是执行上面 Alex 建议的操作,这是您的原始设置和建议的解决方案之间的中间立场:每个分区不要有一个项目,或者单个分区中的所有项目,但在中:例如,假设在您的工作量中,您每天收集 100MB 的数据。所以你使用天数作为分区键(而不是你的布尔值)。某一天的所有数据将位于一个分区中。里面每天的分区,不同的条目(行)将按聚类键顺序排序,即时间。使用此设置,要在某个特定日期后检索所有项目,只需开始逐日查询即可。例如,查询第 134 天,然后是第 135 天,然后是第 136 天,然后等等……在每一天中,结果将已经排序。所以问题解决了。

这种技术是一种相当著名的“时间序列”数据建模。Scylla(和 Cassandra)甚至为此建模调整了特殊的压缩策略 TWCS(时间窗口压缩策略)。

于 2019-04-04T19:09:06.803 回答
1

已经回答了类似的问题。例如这里:Cassandra 数据建模:时间戳作为分区键

您需要设计一个合适的分区键,可能是年份,具体取决于预期的数据量

于 2019-03-11T06:34:48.987 回答