Cassandra-2.1.2 中的范围扫描需要大量时间
Posted
技术标签:
【中文标题】Cassandra-2.1.2 中的范围扫描需要大量时间【英文标题】:Range Scan in Cassandra-2.1.2 taking a lot of time 【发布时间】:2015-01-14 07:41:08 【问题描述】:我的用例是这样的:我在一个表中插入 1000 万行,描述如下:
keyval bigint, rangef bigint, arrayval blob, PRIMARY KEY (rangef, keyval)
输入数据如下-
keyval - some timestamp
rangef - a random number
arrayval - a byte array
我将我的主键作为复合键,因为在插入 1000 万行后,我想对 keyval 执行范围扫描。由于 keyval 包含时间戳,我的查询将是这样的,给我这次到这次之间的所有行。因此,为了执行这些类型的 Select 查询,我将主键作为复合键。
现在,在摄取时,性能非常好且令人满意。但是当我运行上述查询时,性能非常低。当我查询时 - 将 t1 和 t1 + 3 分钟内的所有行带给我,在 160 秒内返回了近 50 万条记录。
我的查询是这样的
Statement s = QueryBuilder.select().all().from(keySpace, tableName).allowFiltering().where(QueryBuilder.gte("keyval", 1411516800)).and(QueryBuilder.lte("keyval", 1411516980));
s.setFetchSize(10000);
ResultSet rs = sess.execute(s);
for (Row row : rs)
count++;
System.out.println("Batch2 count = " + count);
我使用的是默认分区器,即 MurMur 分区器。
我的集群配置是 -
没有。节点数 - 4 种子节点数 - 1 磁盘数量 - 6 每个节点的 MAX_HEAP_SIZE = 8G
其余配置为默认配置。
如何提高范围扫描性能?
【问题讨论】:
【参考方案1】:您实际上是在执行全表扫描,而不是范围扫描。这是 Cassandra 可能最慢的查询之一,通常仅由分析工作负载使用。如果您的查询在任何时候需要 allow filterting
处理 OLTP 工作负载,则很可能是错误的。基本上,Cassandra 在设计时就知道需要访问整个数据集的查询不会扩展,因此付出了很大的努力来简化分区和快速访问分区内的数据。
要解决此问题,您需要重新考虑数据模型并考虑如何将数据限制为单个分区上的查询。
【讨论】:
即使他使用一个分区,如果行真的很大(数百万长度),他可能会遇到超时。如果扫描只占用行的一小部分,则 OP 还应该重新考虑他的方案。 哦,是的,我的意思是查询应该只命中一个分区。并不是说应该只有一个分区。【参考方案2】:RussS 是正确的,您的问题是由使用 ALLOW FILTERING
引起的,并且您没有将查询限制在单个分区。
如何提高范围扫描性能?
通过使用分区键值来限制查询。
PRIMARY KEY (rangef, keyval)
如果上面确实是正确的,那么rangef
就是你的分区键。更改您的查询以首先限制rangef
的特定值(如RussS 建议的“单一分区”)。然后,您对集群键 keyval
的当前范围查询应该可以工作。
现在,该查询可能不会返回任何对您有用的信息。或者您可能必须在应用程序端遍历许多 rangef
值,这可能很麻烦。这是您需要重新评估您的数据模型并提出适当的键来划分数据的地方。
我在 Keyval 上做了二级索引,我的查询性能得到了提升。从 160 秒下降到 40 秒。那么索引 Keyval 字段有意义吗?
依赖二级索引的问题在于,它们一开始可能看起来很快,但随着时间的推移会变慢。尤其是对于时间戳(Keyval)这样的高基数列,二级索引查询必须走遍每个节点,最终扫描大量行以获取少量结果。在新的查询表中复制数据总是比依赖二级索引查询要好。
【讨论】:
我知道我必须更改我的架构或数据模型。我的数据模型是这样的,因为现在我只是在评估 Cassandra。我的实际数据会有所不同,因此我的数据模型肯定会改变。感谢您的宝贵建议。 再更新一次,我在Keyval上做了二级索引,查询性能提升了。从 160 秒下降到 40 秒。那么索引 Keyval 字段有意义吗?以上是关于Cassandra-2.1.2 中的范围扫描需要大量时间的主要内容,如果未能解决你的问题,请参考以下文章