索引列上的cassandra过滤不起作用

时间:2014-12-12 10:40:34

标签: cassandra

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

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

我创建了下表:

CREATE TABLE active_accounts
(
    customer_name   text, 
    account_name    text, 
    date            timestamp, 
    PRIMARY KEY ((customer_name, account_name))
);

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

CREATE INDEX ON active_accounts (date);

当我插入一些数据时,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);

这正是我所希望的 - 我不会获得庞大的数据表,而且表中的每个条目都代表一个独特的客户帐户 - 所以不需要选择不同的。

我想提出的问题 - 在过去一个月内有多少个不同的客户帐户处于活动状态说:

 Select count(*) from active_accounts where date >= 1418377411000 and date <= 1418397411000 ALLOW FILTERING;

为了回应此查询,我收到以下错误:

code=2200 [Invalid query] message="No indexed columns present in by-columns clause with Equal operator"

我缺少什么;这不是我创建的索引的目的吗?

1 个答案:

答案 0 :(得分: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))
);

此架构仅对看起来像

的查询有效

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

此表的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)
);

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

node 1: [ (May 1 1999) -> [(May 2 1999, Bob, 1), (May 15 1999,Tom,32)]

这会在每个分区中按顺序放置帐户日期,这使得在特定日期之间进行范围切片非常快。不幸的是,您必须在应用程序端添加代码以缩短查询可能跨越的多个月。此架构需要大量(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中,辅助索引存在于群集中的每个节点上。这意味着任何需要二级索引的查询都必须要求联系群集中的每个节点。随着集群的增长,这将变得越来越不具备性能,并且绝对不是您想要频繁查询的东西。