用于每小时查询的Cassandra模式

用于每小时查询的Cassandra模式,cassandra,Cassandra,我想在Cassandra中存储来自多个来源的数据,并每小时运行一次作业,只处理特定时间的数据点。用于此目的的最佳模式是什么 为了避免出现热点,我不能将一个小时的所有数据放在一个分区中,因此每个小时的数据需要分布在多个分区中 因此,我看到了两种允许按小时查询的方法: 为每小时创建一个新表,并对该表执行select*,不使用where子句读取该小时。我认为这对于读和写来说是很有效的,但是要管理这么多表会很烦人 每周创建一个新表,为一周内的小时数(即1到168)创建一列,并在其上创建一个二级索引。然后

我想在Cassandra中存储来自多个来源的数据,并每小时运行一次作业,只处理特定时间的数据点。用于此目的的最佳模式是什么

为了避免出现热点,我不能将一个小时的所有数据放在一个分区中,因此每个小时的数据需要分布在多个分区中

因此,我看到了两种允许按小时查询的方法:

为每小时创建一个新表,并对该表执行select*,不使用where子句读取该小时。我认为这对于读和写来说是很有效的,但是要管理这么多表会很烦人

每周创建一个新表,为一周内的小时数(即1到168)创建一列,并在其上创建一个二级索引。然后我可以做一个选择,其中hour=x。这似乎是可行的,但我担心如果有很多行,它将无法很好地扩展

有人知道哪种方法可以更好地扩展吗?有更好的方法吗


谢谢。

您没有太多选择,而且,正如您已经发现的,解决方案也有缺点

由于与二级索引相关的可伸缩性问题,我肯定会避免解决方案2。如果您现在需要解决方案,我会使用许多表。如果你能等一下,我会用Cassandra 3并选择一个合适的键

嗯,,
卡洛

在这种情况下,你可以使用桶。bucket是将分区拆分为几个独立部分的一种方法。例如,假设您的模式如下所示: 使用复制创建密钥空间时间序列={ “类”:“SimpleStrategy”,“复制因子”:1 }; 使用时间序列; 每小时创建一次表 源id文本, 小时文本, 日期时间戳, 数据文本, bucket int, 主键小时、存储桶、日期 ;

然后,您可以使用bucket将小时划分为10个分区,例如,使用某个已知标识符(如source_id)的散列函数

在查询时,您需要指定小时,通常是所有存储桶:

从小时数中选择*,其中小时数='2015-07-20 23:00',桶数为0,1,2,3,4,5,6,7,8,9

散列函数很重要,因为您希望它在不同分区之间均匀地分布数据,即使要散列的已标识分区不是均匀分布的,但您也不希望它是一个非常复杂的函数

这个JSFIDLE为您提供了一个非常简单的哈希函数示例,它均匀地分布数据,并且可以轻松地用任何语言复制:


否则,代替哈希函数,id的模或者甚至纪元时间的模可以代替哈希函数,但如果使用id的模,则必须检查数字是否以统一的模式结束。另一方面,如果取时间戳的模,您将在一段时间内有效地将所有内容写入一个bucket,这可能会创建热点,特别是在bucket数量较少的情况下。

指定所有bucket将导致Cassandra联系许多可能全部的节点,具体取决于读取操作期间的集群大小节点。这是可伸缩性的一个限制。您不能分发数据以避免热点,同时避免与拥有数据的节点联系。在任何情况下,都可以控制示例中10个节点的数量。我也在生产中使用它来处理非常大的数据集,没有任何问题。当然,这就像你说的-问题是在查询时,你不知道10个分区中的哪个包含数据,所以当你应该只联系一个时,你会联系所有的节点。我并不是说这不起作用,只是不存在一个干净且有效的解决方案。@joscas若我散列到N个bucket,似乎我可以使用N个客户端并行处理每小时的数据片段,这将大大提高性能。如果我在每个C*节点上运行一个客户机,是否有一种方法可以利用数据局部性,这样每个客户机都可以读取它所运行的节点的本地数据?i、 e.火花连接器的工作方式,但不使用spark@JimMeyer是的,你可以做一些努力。在任何情况下,我认为DataStax C*驱动程序为您提供了许多选项来扩展读取负载。首先要使用DataStax java驱动程序和TokenAwarePolicy Hi Carlo,在物化视图中我会使用什么键?如果我使用日期和时间作为分区键,那么看起来我又回到了物化视图中的热点。据我所知,物化视图是随着基表中的每个插入而更新的,而不是惰性地进行计算。