这是一个新的分布式系统和高速互联网环境的用户经常问的问题.
为什么用COUNT()在表中执行分区计数在Cassandra中不是一个好主意?
发布于 2022-07-19 05:43:38
我们经常遇到的问题之一是用户试图在Cassandra中执行COUNT()。很多时候,他们问的问题是“为什么要超时?”为什么是真的?
作为关系数据库(RDBMS)的DBA,在表中执行记录计数是您经常做的事情。这个问题的答案很简单,但它需要了解分布式体系结构的基本原理和Cassandra的工作原理。让我们开始..。
Cassandra使用日志结构合并树存储数据。简单地说,这意味着写入(INSERT、UPDATE和DELETE语句)以顺序方式(如日志文件)以某种间隔写入磁盘。这些名为SSTables的文件是不可变的,这意味着它们在写入磁盘后不会更改,因此avoiding在写入之前读取,使得writes非常快速地。
考虑一个具有多列的简单表。在一天的正常过程中,在表中插入一个新的分区,其中包含2列的值。在某种程度上,可记忆被刷新到以可测性形式编写的磁盘上.。这个新插入的分区相当于一个记录。
一段时间后,同一分区中的另一列被插入到表中。这也算作一项记录。几秒钟后,插入同一分区中的另一列,然后将memtable刷新到磁盘。因为同一分区的这两个片段同时在memtable中,所以在写入SSTable之前,它们被合并在一起,因此只能“计算”为一条记录。
当天晚些时候,同一分区的一个现有列将被更新为一个新值。由于Cassandra在将写入磁盘之前不执行读操作,所以Cassandra不知道分区的列是否已经存在于其他SSTables中,因此更新只是作为另一条记录插入,这最终使其成为另一个SSTable (是的,在Cassandra中的更新只是插入下面的内容,也就是“鞋帮”。)。
在本例中,3条记录存在于3种不同的SSTables中,它们实际上是同一个分区的fragments。但卡桑德拉不知道这3条记录是同一个分区,直到它读取该分区。实际上,这就是无限的COUNT()所做的事情:
才能得到结果。
在小型集群中的一个小表上,运行计数查询并不是什么大事。但是,想象一下,如果在一个具有数十个节点的集群中,有数百个SSTables值超过500 on。看到这么简单的查询怎么变得如此昂贵了吗?它必须在集群中执行<#>full表扫描,这就是为什么查询在有机会完成之前就会超时-- <#>it不缩放。
更复杂的是,考虑到当计数正在进行时,分区不断地被创建和更新--毕竟这是大数据,而且您使用Cassandra是因为您有a比例问题。即使你足够幸运地得到了结果,那算有效吗?might也在计算星号。因为当你计算出夜空中有一半的恒星有足够的时间时,your计数可能就过时了--因为宇宙不是静止的--新恒星诞生了,老恒星一直在消亡。类似地,<#>your表不是静态的 --创建了新分区,更新了现有分区,甚至删除了一些分区。
“我可以用柜台吗?”,你问。也许吧。如果您的用例是这样的,您只编写分区一次,并且永远不会覆盖它。如果您的用例涉及覆盖,那么您就无法确定它是否是第一次写入,因此您的计数器就变得无用了。您可能会想出某种算法并以某种方式存储计数,但在所有可能的情况下,your“计数器”解决方案不会缩放,因为它可能会涉及(a)读前写入,(b)对每个操作附加写,或者(c)两者兼而有之。
您可以从get中获得一个估计值,但这正是您将得到的--估计值。这是因为它有同样的问题。当Cassandra将memtable刷新到磁盘时,它知道该SSTable中有多少键,并相应地更新表状态。当我们在这里的时候,请注意删除也是在掩码下插入的。,即墓碑被插入到表中,因此它被计算在tablestats中。只有在gc_grace_seconds后,墓碑被压实后,它才会减少。
最后,如果你真的必须做一个计数,做DSE分析或DSE搜索,但这些是为另一个博客文章。等我数完星星以后再去查,也许.
我已经过度简化了表状态更新所发生的事情,从而简化了对预期受众的消化。实际上使用了HyperLogLog等算法,提高了聚类值的准确性。
在我第一次发表这个博客两年之后,DataStax散装装载机 (也就是DSBulk)出现了。它是一个从Apache高效加载和卸载数据的工具,尽管这不是它的能力范围。
DSBulk以分布式方式为在大型表中计数数据提供了一个很好的特性。它是以CSV或JSON格式加载或卸载数据的推荐工具。它的执行速度比cqlsh COPY命令快4倍。
没错,免费提供给开放源代码的Apache Cassandra用户.。有关详细信息,请参阅用DSBulk计数表中的数据。干杯!
https://dba.stackexchange.com/questions/314567
复制相似问题