为日期查询构造cassandra表

scyqe7ek  于 2021-06-13  发布在  Cassandra
关注(0)|答案(1)|浏览(301)

我在学习Cassandra,作为一个实践数据集,我从雅虎获取历史股票数据。每个交易日将有一个记录。
显然,我需要将股票符号作为分区键的一部分。我看到了一些相互矛盾的信息,关于是应该将日期作为分区键的一部分,还是将其作为集群列?
实际上,股市每年开放253天。因此,一只股票每年将有253条记录。我没有建立一个全面的数据库,但想设计它,以适应/正确。
如果我将日期作为分区键的一部分,那么它不可能分布在节点上吗?使日期范围查询变慢?

6rqinv9w

6rqinv9w1#

如果我将日期作为分区键的一部分,那么它不可能分布在节点上吗?使日期范围查询变慢?
是的,两种说法都正确。这种建模方法称为“时间bucketing”,它的主要用例是针对随时间增长的时间/事件数据。好消息是,你不需要这么做,除非你的分区被设计得很大。如果您当前的预测是每年每个分区写253行,那么每年只能<40kb(请参阅使用 nodetool tablehistograms 下面)。
为了你的目的,我认为 symbol 并按 day 应该够了。

CREATE TABLE stockquotes (
 symbol text,
 day date,
 price decimal,
 PRIMARY KEY(symbol, day))
 WITH CLUSTERING ORDER BY (day DESC);

对于大多数基于时间的用例,我们倾向于更关心最近的数据(对于您的用例,这可能是真的,也可能不是真的)。如果是,则按降序写入数据 day 将提高这些查询的性能。
然后(在写入一些数据之后),像这样的日期范围查询将工作:

SELECT * FROM stockquotes 
WHERE symbol='AAPL'
  AND day >= '2020-08-01' AND day < '2020-08-08';

 symbol | day        | price
--------+------------+--------
   AAPL | 2020-08-07 | 444.45
   AAPL | 2020-08-06 | 455.61
   AAPL | 2020-08-05 | 440.25
   AAPL | 2020-08-04 | 438.66
   AAPL | 2020-08-03 | 435.75

(5 rows)

验证分区大小可以使用 nodetool tablehistograms (数据刷新到磁盘后)。

bin/nodetool tablehistograms stackoverflow.stockquotes
stackoverflow/stockquotes histograms
Percentile      Read Latency     Write Latency          SSTables    Partition Size        Cell Count
                    (micros)          (micros)                             (bytes)
50%                     0.00              0.00              0.00               124                 5
75%                     0.00              0.00              0.00               124                 5
95%                     0.00              0.00              0.00               124                 5
98%                     0.00              0.00              0.00               124                 5
99%                     0.00              0.00              0.00               124                 5
Min                     0.00              0.00              0.00               104                 5
Max                     0.00              0.00              0.00               124                 5

每年的分区大小=124字节x 253=31kb
考虑到很小的分区大小,这个模型可能至少可以保存30年的数据,然后才会出现任何减速(我建议保持分区小于等于1mb)。也许是因为 quartercentiry 够了吗?不管怎样,短期内,一切都会好起来的。
编辑:
似乎pk中使用的任何日期部分都会将数据分散到节点上,不是吗?
是的,分区键中使用的日期部分会将数据分布在节点上。这才是真正的意义所在。您不希望以非绑定行增长的反模式结束,因为分区最终会变得太大而无法使用。这个想法完全是为了确保足够的数据分发。
假设是1/秒,我需要跨年查询,等等。这种bucketing是如何工作的?
因此,时间限制的诀窍是在数据分布和查询灵活性之间找到一个“快乐的媒介”。不幸的是,在边缘情况下,查询可能会命中多个分区(节点)。但我们的想法是建立一个模型来很好地处理大多数问题。
这里的例子问题是1/秒一年,有点极端。但解决问题的思路是一样的。一天有86400秒。根据行的大小,这甚至可能是太多的桶一天。但为了论证,说我们可以。如果我们在一天内完成任务,pk看起来是这样的:

PRIMARY KEY ((symbol,day),timestamp)

以及 WHERE 子句开始如下所示:

WHERE symbol='AAPL' AND day IN ('2020-08-06','2020-08-07');

另一方面,几天就可以了,但是查询一整年的时间会很麻烦。另外,我们不想建立一个 IN 第253天条款。事实上,我不建议人们在一个月内超过个位数 IN .
这里一种可能的方法是从应用程序中激发253个异步查询(每天一个),然后在那里组装和排序结果集。在这里,使用spark(在rdd中做任何事情)也是一个不错的选择。实际上,cassandra并不是一个很好的报表api数据库,因此探索一些附加工具是有价值的。

相关问题