我的用例是这样的:我在一个表中插入了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秒内返回了近500k的记录。
我的查询就像这样
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
休息配置是默认配置。
如何提高我的范围扫描性能?
答案 0 :(得分:3)
您实际上是在执行全表扫描而不是范围扫描。这是Cassandra可能的最慢查询之一,通常仅供分析工作负载使用。如果您的查询在任何时候对OLTP工作负载需要allow filterting
,则很可能是错误的。基本上Cassandra的设计理念是,需要访问整个数据集的查询不会扩展,因此需要付出大量努力才能使分区和快速访问分区内的数据变得简单。
要解决此问题,您需要重新考虑数据模型,并考虑如何将数据限制为单个分区上的查询。
答案 1 :(得分:2)
RussS是正确的,您的问题是由使用ALLOW FILTERING
导致的,并且您不是将查询限制在单个分区。
如何提高我的范围扫描性能?
通过使用分区键的值限制查询。
PRIMARY KEY (rangef, keyval)
如果上述内容确实正确,则rangef
是您的分区键。更改您的查询以首先限制rangef
的特定值("单个分区",如RussS建议的那样)。然后,您的群集密钥keyval
上的当前范围查询应该有效。
现在,该查询可能不会返回对您有用的任何内容。或者您可能必须在应用程序端迭代许多rangef
值,这可能很麻烦。在这里,您需要重新评估数据模型,并提供适当的密钥来对数据进行分区。
我在Keyval上创建了二级索引,我的查询性能得到了提升。从160秒开始,它下降到40秒。索引Keyval字段是否有意义?
依赖二级索引的问题在于它们起初可能看起来很快,但随着时间的推移会变慢。特别是对于像时间戳(Keyval)这样的高基数列,辅助索引查询必须遍历每个节点并最终扫描大量行以获得少量结果。在新的查询表中复制数据总比在依赖二级索引查询时更好。