Nosql 卡桑德拉高效桌上步行

Nosql 卡桑德拉高效桌上步行,nosql,cassandra,sum,aggregate-functions,full-table-scan,Nosql,Cassandra,Sum,Aggregate Functions,Full Table Scan,我目前正在做一个基准测试(这是我学士学位论文的一部分),该测试比较基于抽象数据模型和抽象查询的SQL和NoSQL数据库,以在所有系统上实现公平的实现 我目前正在执行一个查询,具体如下: 我有一张卡桑德拉表格,具体如下: CREATE TABLE allocated( partition_key int, financial_institution varchar, primary_uuid uuid, report_name varchar, view

我目前正在做一个基准测试(这是我学士学位论文的一部分),该测试比较基于抽象数据模型和抽象查询的SQL和NoSQL数据库,以在所有系统上实现公平的实现

我目前正在执行一个查询,具体如下: 我有一张卡桑德拉表格,具体如下:

CREATE TABLE allocated(
    partition_key int, 
    financial_institution varchar, 
    primary_uuid uuid,
    report_name varchar,
    view_name varchar,
    row_name varchar,
    col_name varchar,
    amount float,
PRIMARY KEY (partition_key, report_name, primary_uuid));
SELECT 
   partition_key, 
   financial_institution,
   report_name, 
   view_name, 
   col_name, 
   row_name, 
   amount 
FROM allocated; 
此表包含大约100000000条记录(~300GB)

现在,我们需要计算字段“金额””的总和,以计算报表名称视图名称列名称行名称的每种可能组合

在SQL中,这将非常简单,只需选择sum(amount)并按所需字段对其进行分组。 但是,由于Cassandra不支持这些操作(这很好),我需要用另一种方法来实现这一点

目前,我通过执行完整的表遍历、处理每个记录并将每个组合的总和存储在Java的HashMap中来实现这一点。 我使用的准备好的声明如下:

CREATE TABLE allocated(
    partition_key int, 
    financial_institution varchar, 
    primary_uuid uuid,
    report_name varchar,
    view_name varchar,
    row_name varchar,
    col_name varchar,
    amount float,
PRIMARY KEY (partition_key, report_name, primary_uuid));
SELECT 
   partition_key, 
   financial_institution,
   report_name, 
   view_name, 
   col_name, 
   row_name, 
   amount 
FROM allocated; 
对于卡桑德拉(cassandra)和Java应用程序来说,这在内存占用量很大的机器上部分有效,但在较小的机器上崩溃

现在我想知道是否有可能以更快的方式实现这一点? 我可以想象使用partition_键,它也充当cassandra分区键,并对每个分区执行此操作(我有5个分区)

我还想过通过将每个分区和报告分配给一个单独的线程并并行运行来实现多线程。但是我想这会在应用程序端造成很多开销

现在进入实际问题:您会推荐另一种执行策略来实现这一点吗? 也许我仍然以类似SQL的方式思考太多


感谢您的支持。

这里有两个想法可能会对您有所帮助

1) 您可以使用以下方法高效地扫描任何表中的行。考虑一个带有主键的表(PK,SK,TK)。让我们使用1000的获取大小,但您可以尝试其他值

第一个问题(Q1):

处理这些值,然后记录构成主键的三列的值。假设这些值是pk_val、sk_val和tk_val。下面是您的下一个查询(Q2):

上面的查询将查找相同pk和sk的记录,但查找下一个tk值。只要你不断获得1000条记录,就要不断重复。当你得到更少的东西时,你忽略了tk,而在sk上做得更好。以下是查询(第三季度):

同样,只要你有1000行,就继续这样做。完成后,运行以下查询(Q4):

现在,再次使用上一条记录中的pk_val、sk_val、tk_val,然后使用这些值运行Q2,然后运行Q3,然后运行Q4

当第四季度返回的值小于1000时,您就完成了

2) 我假设“报告名称、视图名称、列名称和行名称”不是唯一的,这就是为什么在再次看到相同的组合时,要维护一个hashmap来跟踪总金额。这里有一些可能更有效的方法。在cassandra中创建一个表,其中键是这四个值的组合(可能是分隔的)。如果有三个,您可以简单地为这三个使用复合键。现在,您还需要一个名为amounts的列,它是一个列表。在扫描分配表(使用上述方法)时,针对每一行执行以下操作:

update amounts_table set amounts = amounts + whatever_amount where my_primary_key = four_col_values_delimited;
完成后,您可以扫描此表,计算所看到的每一行的列表总和,并将其转储到任何需要的位置。请注意,由于只有一个密钥,因此只能使用令牌(主密钥)>令牌(主密钥的最后一个值)进行扫描


对不起,如果我的描述令人困惑。如果这有帮助,请告诉我。

到#2)我可能会以这种方式重新实现它。对我来说,这听起来比我的HashMap实现要好得多,它最终让我昨天的JVM使用了大约2GB的RAM。To#1):我得到了大部分部分的概念。我不确定第三个和第四个问题。假设pk,sk,tk是按层次结构排序的,当第2季度得到的结果少于1000个时,我是否必须立即跳到下一个sk,因为相同(pk,sk)和随机tk的所有组合都已用尽。。。。或者也许我没有得到重点,再次感谢您的帮助:)“假设pk、sk、tk是按层次结构排序的,当第二季度的结果少于1000个时,我不需要立即跳到下一个sk吗?”当第二季度返回的结果少于1000个时,您知道当前pk_val、sk_val组合没有更多的值(所有tk_val都已扫描)。因此,您需要查找同一pk_val的下一个sk值,这可以使用Q3完成。(很抱歉进行编辑,但我没有意识到按enter键会发布注释。此外,注释中的格式似乎不起作用。)。
select whatever_columns from allocated where token(pk) > token(pk_val) limit 1000;
update amounts_table set amounts = amounts + whatever_amount where my_primary_key = four_col_values_delimited;