我在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,是否有更好/合适的方法来做到这一点?
答案 0 :(得分:1)
您添加一个布尔键并始终将其设置为yes的解决方案基本上会创建一个包含所有数据的巨大分区。这很少是您真正想要的。如果该分区是您的全部数据,则意味着即使您有一个10节点群集,每个节点上有8个CPU,群集中所有80个CPU中只有3个CPU会做任何工作(因为每个分区都属于一个特定的CPU,RF = 3时有三个副本。
如果您想知道为什么原始解决方案不起作用,而Scylla拒绝了“ ORDER BY”,那么问题在于,尽管Scylla可以扫描整个表以在X时刻后查找条目(您需要将“允许过滤”添加到查询中),它没有有效的方法来按时间排序。在内部,不同的分区不是按分区键排序的,而是按“令牌”(分区键的哈希函数)排序的。这种具有随机化效果的散列对于平衡集群上所有CPU之间的负载很重要,但可以防止Scylla(或Cassandra)按原始键顺序读取分区。
您可以做的一件事情是做Alex上面建议的事情,这是您在原始设置和建议的解决方案之间的中间立场:每个分区没有一个项目,或者一个分区中没有所有项目,但是中间的东西:例如,想象在您的工作负载中,每天收集100MB的数据。因此,您将天数用作分区键(而不是布尔值)。某一天的所有数据将位于一个分区中。 在内部,每天的分区中,不同的条目(行)将按照聚类键顺序(时间)进行排序。使用此设置,要在某个特定日期之后检索所有项目,只需开始逐日查询每一天。例如,查询第134天,然后查询第135天,查询136,然后查询,依此类推...在每一天之内,结果将已经排序。这样问题就解决了。
此技术是相当知名的“时间序列”数据建模。 Scylla(和Cassandra)甚至为此模型调整了一种特殊的压缩策略,即TWCS(时间窗口压缩策略)。