在完全复制的Cassandra集群上执行非主键查询

Kia*_*ani 2 replication eventual-consistency cassandra

我在使用Docker容器的单台机器上设置了一个完全复制的3节点Cassandra集群,具有以下状态:

Datacenter: dc_n1
=================
Status Address Load Tokens Owns Host_ID Rack
UN 172.18.0.3 83.98 MiB 256 100.0% 5bf rack_n1

Datacenter: dc_n2
=================
Status Address Load Tokens Owns Host_ID Rack
UN 172.18.0.6 83.52 MiB 256 100.0% 0518 rack_n2

Datacenter: dc_n3
=================
Status Address Load Tokens Owns Host_ID Rack
UN 172.18.0.2 83.52 MiB 256 100.0% ca95 rack_n3

现在考虑以下键空间:

create KEYSPACE stackoverflow WITH replication = {'class': 'NetworkTopologyStrategy', 'dc_n1':1,'dc_n2':1,'dc_n3':1};

和一个定义为的表(假设T_notID是唯一的):

create TABLE stackoverflow.TABLE (T_ID int PRIMARY KEY, T_notID int, T_Data text);

当我发送一个(例如,一百个)并发Java线程向Cassandra节点提交以下两个JDBC查询(重复,一分钟)时,我看到(B)查询的性能下降100倍:

(A)SELECT T_Data FROM TABLE WHERE T_ID =?

(B)SELECT T_Data FROM TABLE WHERE T_notID =?允许过滤

(B)查询还会引发许多Cassandra错误com.datastax.driver.core.exceptions.ReadTimeoutException: Cassandra timeout during read query at consistency ONE (timeout while waiting for repair of inconsistent replica):

我理解,一般来说,在查询中使用"允许过滤"是一种反模式,应该非常谨慎地使用,但在上面的简化示例中,由于数据是完全复制的,每个项目的一个副本驻留在每个节点上,我不明白为什么PK查询和nonPK查询的行为不同.

换句话说,考虑到read consistency这种情况,ONE并且每个节点都可以响应查询而不与集群中的其他节点通信(无论主键定义如何),我本来期望从Cassandra到集中式SQL数据库的类似行为.

有人可以向我解释为什么会发生这种情况和/或我如何解决它?

Ale*_*Ott 5

当您对分区键有条件时 - Cassandra知道数据在磁盘上的位置,并且可以跳转到分区的开始并按顺序读取数据.但是如果你对非分区有条件,那么你的查询将需要遍历所有数据并过滤掉必要的部分 - 你没有任何索引可以让Cassandra找出数据所在的位置.

如果您需要经常运行查询T_notID,那么您可以创建物化视图或二级索引(但您需要了解它们具有哪些限制).

DataStax有一篇关于ALLOW FILTERING 的非常好的博文,以及它可以在何处使用.