2

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

我目前正在执行如下指定的查询:我在 Cassandra 中有一个表,指定如下:

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));

该表包含大约 100,000,000 条记录 (~300GB)。

我们现在需要为report_nameview_namecol_namerow_name的每个可能组合计算字段“数量”的总和。

在 SQL 中,这很容易,只需选择 sum(金额)并按您想要的字段对其进行分组。但是,由于 Cassandra 不支持这些操作(这非常好),我需要以另一种方式实现这一点。

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

SELECT 
   partition_key, 
   financial_institution,
   report_name, 
   view_name, 
   col_name, 
   row_name, 
   amount 
FROM allocated; 

这部分适用于 cassandra 和 Java 应用程序具有大量 RAM 的机器,但在较小的机器上会崩溃。

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

我也想通过分配每个分区并报告给一个单独的线程并并行运行它来完成这个多线程。但我想这会在应用程序方面造成很多开销。

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

感谢您的支持。

4

1 回答 1

3

这里有两个想法可以帮助你。

1)您可以使用以下方法有效地扫描任何表中的行。考虑一个带有 PRIMARY KEY (pk, sk, tk) 的表。让我们使用 1000 的提取大小,但您可以尝试其他值。

第一个查询(Q1):

select whatever_columns from allocated limit 1000;

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

select whatever_columns from allocated where token(pk) = token(pk_val) and sk = sk_val and tk > tk_val limit 1000;

上述查询将查找相同 pk 和 sk 的记录,但查找 tk 的下一个值。只要您不断获得 1000 条记录,就不断重复。当得到更少的东西时,你会忽略 tk,而在 sk 上做得更大。这是查询(Q3):

select whatever_columns from allocated where token(pk) = token(pk_val) and sk > sk_val limit 1000;

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

select whatever_columns from allocated where token(pk) > token(pk_val) limit 1000;

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

当 Q4 返回小于 1000 时,您就完成了。

2) 我假设'report_name、view_name、col_name 和 row_name' 不是唯一的,这就是为什么当你再次看到相同的组合时你维护一个哈希图来跟踪总量。这是一些可能会更好的方法。在 cassandra 中创建一个表,其中键是这四个值的组合(可能是分隔的)。如果有三个,您可以简单地为这三个使用复合键。现在,您还需要一个名为数量的列,它是一个列表。当您扫描分配表时(使用上述方法),对于每一行,您执行以下操作:

update amounts_table set amounts = amounts + whatever_amount where my_primary_key = four_col_values_delimited;

完成后,您可以扫描此表并计算您看到的每一行的列表总和,并将其转储到您想要的任何位置。请注意,由于只有一个键,因此您只能使用 token(primary_key) > token(last_value_of_primary_key) 进行扫描。

对不起,如果我的描述令人困惑。请让我知道这可不可以帮你。

于 2014-01-19T07:47:13.860 回答