有没有办法有效地计算 Cassandra 中一个非常大的分区的行数?

Is there a way to effectively count rows of a very huge partition in Cassandra?

我有非常庞大的 Cassandra table,其中包含超过 10 亿条记录。我的主键形式如下:“(partition_id, cluster_id1, cluster_id2)”。现在对于几个特定的​​ partition_id,我有太多记录,如果不引发超时异常,我无法 运行 对这些分区键进行行计数。

我在cqlsh中运行的是:

SELECT count(*) FROM relation WHERE partition_id='some_huge_partition';

我遇到了这个异常:

ReadTimeout: Error from server: code=1200 [Coordinator node timed out waiting for replica nodes' responses] message="Operation timed out - received only 0 responses." info={'received_responses': 0, 'required_responses': 1, 'consistency': 'ONE'}

我尝试设置 --connect-timeout--request-timeout,但没有成功。我在 ElasticSearch 中统计了相同的数据,行数大约为 3000 万(同一分区)。

我的 Cassandra 是 3.11.2,CQLSH 是 5.0.1。 Cassandra 集群包含 3 个节点,每个节点有更多的 1T 硬盘(相当老的服务器,超过 8 年)。

简而言之,我的问题是:

  1. 我怎么算呢?甚至可以在 Cassandra 中计算一个巨大的分区吗?
  2. 我可以使用带有分区键的 COPY TO 命令作为过滤器,以便我可以在导出的 CSV 文件中对其进行计数吗?
  3. 有没有一种方法可以在任何分区变得太大之前监控插入过程?

非常感谢高级。

是的,使用 Cassandra 很难处理大分区。确实没有监控特定分区大小的好方法,尽管 Cassandra 会警告在 system.log 中写入大分区。未绑定分区增长是您在创建 table 期间需要解决的问题,它涉及添加额外的(通常基于时间的)分区键,这些分区键源自对您的业务用例的理解。

这里的答案是,您可以使用COPY命令导出分区中的数据。为了防止它超时,您需要使用 PAGESIZEPAGETIMEOUT 选项,有点像这样:

COPY products TO '/home/aploetz/products.txt'
  WITH DELIMITER='|' AND HEADER=true
  AND PAGETIMEOUT=40 AND PAGESIZE=20;

这会将 products table 导出到 pipe-delimited 文件,header,页面大小一次为 20 行,40每个页面获取的第二次超时。

如果仍然超时,请尝试减少 PAGESIZE and/or 增加 PAGETIMEOUT.

我发现借助 Spark 和很棒的 Spark Cassandra Connector 库,我终于可以计算一个大的 table 而不会遇到任何超时限制。 Python Spark代码是这样的:

tbl_user_activity = sqlContext.read.format("org.apache.spark.sql.cassandra").options(keyspace='ks1', table='user_activity').load()
tbl_user_activity.where('id = 1').count()

它会 运行 一段时间,但最终会起作用。