索引列上的cassandra过滤无效

sta*_*ser 1 cassandra

我正在使用(最新版本)Cassandra nosql dbms来建模一些数据.

我想了解上个月活跃客户帐户的数量.

我创建了下表:

CREATE TABLE active_accounts
(
    customer_name   text, 
    account_name    text, 
    date            timestamp, 
    PRIMARY KEY ((customer_name, account_name))
);
Run Code Online (Sandbox Code Playgroud)

因为我想按日期过滤,我在日期列上创建了一个索引:

CREATE INDEX ON active_accounts (date);
Run Code Online (Sandbox Code Playgroud)

当我插入一些数据时,Cassandra会自动更新任何现有主键匹配的数据,因此以下插入只生成两条记录:

insert into active_accounts (customer_name, account_name, date) Values ('customer2', 'account2', 1418377413000);
insert into active_accounts (customer_name, account_name, date) Values ('customer1', 'account1', 1418377413000);
insert into active_accounts (customer_name, account_name, date) Values ('customer2', 'account2', 1418377414000);
insert into active_accounts (customer_name, account_name, date) Values ('customer2', 'account2', 1418377415000);
Run Code Online (Sandbox Code Playgroud)

这正是我想要的 - 我不会得到一个庞大的数据表,表中的每个条目代表一个独特的客户帐户 - 所以不需要选择不同的.

我想提出的问题是:上个月有多少不同的客户帐户处于活动状态:

 Select count(*) from active_accounts where date >= 1418377411000 and date <= 1418397411000 ALLOW FILTERING;
Run Code Online (Sandbox Code Playgroud)

在回应此查询时,我收到以下错误:

code=2200 [Invalid query] message="No indexed columns present in by-columns clause with Equal operator"
Run Code Online (Sandbox Code Playgroud)

我错过了什么; 这不是我创建的索引的目的吗?

Rus*_*ssS 7

Cassandra中的表设计非常重要,它必须与您尝试执行的查询类型相匹配.Cassandra试图阻止您对日期列执行查询的原因是该列中的任何查询都将非常低效.

表设计 - 为查询建模

Cassandra可以快速运行的一个主要原因是它对用户数据进行分区,以便在不联系群集中的所有节点的情况下完成大多数(99%)查询.这意味着更少的网络流量,更少的磁盘访问和更快的响应时间.不幸的是,Cassandra无法自动确定分区数据的最佳方式.最终用户必须确定适合C*datamodel的架构,并允许高速查询.

CREATE TABLE active_accounts
(
   customer_name   text, 
   account_name    text, 
   date            timestamp, 
   PRIMARY KEY ((customer_name, account_name))
);
Run Code Online (Sandbox Code Playgroud)

此架构仅对看起来像的查询有效

SELECT timestamp FROM active_accounts where customer_name =?和account_name =?

这是因为在集群上数据实际上将被存储为

node 1: [ ((Bob,1)->Monday), ((Tom,32)->Tuesday)]
node 2: [ ((Candice, 3) -> Friday), ((Sarah,1) -> Monday)]
Run Code Online (Sandbox Code Playgroud)

此表的PRIMARY KEY表示应根据CustomerName和AccountName组合的哈希将数据放在节点上.这意味着如果我们同时拥有这两个数据,我们只能快速查找数据.超出该范围的任何内容都将成为批处理作业,因为它需要命中多个节点并过滤表中的所有数据.

要优化不同的查询,您需要更改表的布局或使用Spark或Hadoop等分布式分析框架.

可能适用于您的目的的不同表模式的示例将是类似的

CREATE TABLE active_accounts
(
    start_month     timestamp,
    customer_name   text, 
    account_name    text, 
    date            timestamp, 
    PRIMARY KEY (start_month, date, customer_name, account_name)
);
Run Code Online (Sandbox Code Playgroud)

在这个模式中,我将把每月第一天的时间戳作为分区键,将日期作为第一个聚类键.这意味着在同一个月内发生的多个帐户创建将最终位于同一分区和同一节点上.像这样的模式的数据看起来像

node 1: [ (May 1 1999) -> [(May 2 1999, Bob, 1), (May 15 1999,Tom,32)]
Run Code Online (Sandbox Code Playgroud)

这会将帐户日期按顺序放置在每个分区中,这使得在特定日期之间进行范围切片非常快.不幸的是,您必须在应用程序端添加代码以缩短查询可能跨越的多个月.此架构需要大量(dev)工作,因此如果这些查询非常罕见,则应使用分布式分析平台.

有关此类时间序列建模的更多信息,请查看:

http://planetcassandra.org/getting-started-with-time-series-data-modeling/

一般建模:

http://www.slideshare.net/planetcassandra/cassandra-day-denver-2014-40328174 http://www.slideshare.net/johnny15676/introduction-to-cql-and-data-modeling

Spark和Cassandra:

http://planetcassandra.org/getting-started-with-apache-spark-and-cassandra/

不要使用二级索引

允许过滤被添加到cql语法中,以防止用户意外地设计无法扩展的查询.二级索引实际上仅供那些分析工作或完全理解其含义的C*用户使用.在Cassandra中,辅助索引存在于群集中的每个节点上.这意味着任何需要二级索引的查询都必须要求联系群集中的每个节点.随着集群的增长,这将变得越来越低,并且绝对不是您想要频繁查询的东西.