如何正确选择与索引匹配的分区键

时间:2019-01-09 11:04:38

标签: cassandra cql cql3

我尝试选择在索引列中包含至少一行具有特定值的分区键。

使用当前解决方案可以满足所有其他要求:

  • 能够根据其办公室选择报告。
  • 赋予办公室使用类型和日期范围进行选择的能力。
  • 无需根据日期选择报告,而无需排放办公室和/或报告类型。

最后,我需要能够选择某个用户创建报告的所有办公室。根据cassadra文档,我在用户列上添加了索引。

该表定义为:

create table report(
    office uuid,
    type text,
    insert_date timestamp,
    ...
    created_by uuid,
    ...
    primary key(office, type, insert_date));
create index created_by_idx on report (created_by);

如果我没记错的话,使用该索引就像有一个辅助表,描述如下:

create table report2(
    created_by uuid,
    office uuid,
    type text,
    insert_date timestamp,
    ...
    primary key(created_by ,office, type, insert_date));

我可以成功运行如下查询: select office from report where created_by = ? 但这会导致使用相同的办公室密钥的多行是正确的:每个用户可以在每个办公室中创建多个报告。

现在,我在软件级别过滤重复的办公室,但是我问自己,是否有可能在提取期间直接过滤该数据。

我尝试过: select distinct office from report where created_by = ? 导致 SELECT DISTINCT with WHERE clause only supports restriction by partition key and/or static columns.

然后我尝试了: select office from report where created_by = ? group by office 会给我正确的结果,但会发出警告: Aggregation query used without partition key

这可能是一个问题吗?如何处理cassandra这样的查询,在这种情况下可以忽略此警告?最后,使用这样的查询对 select * ...的where子句相同吗?

1 个答案:

答案 0 :(得分:1)

Cassandra不支持您描述的功能是有原因的-这是因为它效率低下:

首先,如您所述,二级索引必须确实列出所有匹配的行键,而不仅仅是不同的匹配分区键。这是因为您可能会要求所有行,而不仅仅是唯一的分区键,因此数据必须存在。之所以必须将这些数据保留在索引中,另一个原因是每一行都可以单独删除(或过期),因此Cassandra需要跟踪所有这些行,以确定整个分区是否仍然存在,或者不再存在。 / p>

现在,由于我们已经在搜索结果列表中列出了所有行的键,因此仅输出“不同的”分区键是一种低效的操作...如果您在一个分区中有一百万个匹配的行,那么Cassandra将需要在仅输出一个结果之前扫描所有它们。 Cassandra通常不会让用户用低效的操作射击自己的脚(例如,查看如何需要“允许过滤”才能在SELECT查询中明确允许低效的过滤。)

话虽这么说,将来的Cassandra版本应该允许您请求的“ SELECT DISTINCT”请求是合理的,也许要求用户说“ ALLOW FILTERING”以承认它可能很慢。另外,另一种实现可能涉及较慢的更新(每个行更新将检查分区的活动性),但随后需要快速读取。 Scylla考虑了这样的实现,但也没有实现(请参见https://github.com/scylladb/scylla/issues/3435)。