Java Cassandra读取/获取性能
我的Cassandra表具有以下模式Java Cassandra读取/获取性能,java,cassandra,Java,Cassandra,我的Cassandra表具有以下模式 CREATE TABLE cachetable1 ( id text, lsn text, lst timestamp, PRIMARY KEY ((id)) ) WITH bloom_filter_fp_chance=0.010000 AND caching='{"keys":"ALL", "rows_per_partition":"ALL"}' AND comment='' AND dclocal_read_repair_chance=0.100000
CREATE TABLE cachetable1 (
id text,
lsn text,
lst timestamp,
PRIMARY KEY ((id))
) WITH
bloom_filter_fp_chance=0.010000 AND
caching='{"keys":"ALL", "rows_per_partition":"ALL"}' AND
comment='' AND
dclocal_read_repair_chance=0.100000 AND
gc_grace_seconds=864000 AND
read_repair_chance=0.000000 AND
default_time_to_live=0 AND
speculative_retry='99.0PERCENTILE' AND
memtable_flush_period_in_ms=0 AND
compaction={'class': 'SizeTieredCompactionStrategy'} AND
compression={'sstable_compression': 'LZ4Compressor'};
上表包含2.21亿行(约16 GB数据)。CassandraDaemon使用4GB堆空间运行,我为行缓存配置了4GB内存。我尝试从我的java代码中运行select查询,如下所示
for(int i = 0; i < 1000; i ++)
{
int id = random.nextInt(20000000 - 0) + 0;
for(j = id; j <= id + 100; j++)
{
ls.add(j+"");
}
Statement s = QueryBuilder.select("lst","lsn").from("ks1" , "cachetable1").where(QueryBuilder.in("id",ls.toArray()));
s.setFetchSize(100);
ResultSet rs=sess.execute( s );
List<Row> lsr=rs.all();
for(Row rw:lsr)
{
//System.out.println(rw.toString());
count++;
}
ls.clear();
}
for(int i=0;i<1000;i++)
{
int id=random.nextInt(20000000-0)+0;
对于(j=id;j我猜这就是你的罪魁祸首:
.where(QueryBuilder.in("id",ls.toArray()))
在WHERE
子句中使用IN
关系被广泛认为是无效的。在某些情况下,执行多个并行查询可能比在查询中使用一个更快。从:
不在中使用时
…在中使用会降低性能,因为通常必须使用多个节点
查询。例如,在单个本地数据中心群集中,30
节点,复制系数为3,一致性级别为
LOCAL_QUORUM,一个单键查询发送到两个节点,但如果
查询使用中的条件,被查询的节点数为
很可能更高,最多20个节点,具体取决于关键点的位置
属于代币范围
因此,您有两种选择(假设与这个性能差的查询共存不是其中之一):
重写代码,为每个id
发出多个并行请求
重新访问您的数据模型,查看是否有另一个值可以用来为数据设置键。例如,如果ls
中的所有id
s碰巧共享一个唯一的公共列值,这是主键的一个很好的候选值。基本上,找到另一种方法来查询所有id
的主键你正在寻找,并建立一个特定的查询表来支持它
您似乎希望检索100行块中的数据。这听起来是一个很好的集群列候选
将您的模式更改为使用id作为分区键,使用块索引作为群集列,即主键((id),chunk_idx)。插入数据时,您必须了解如何将单个索引映射到id和chunk_idx(例如,可能对其中一个值执行模100以生成块_idx)
现在,当您查询一个id而不指定chunk_idx时,Cassandra可以高效地返回所有100行,并在分区上读取一个磁盘。如果您不总是想读取整个行块,您仍然可以通过指定chunk_idx来执行分区内单个行的范围查询和检索
因此,您的错误是,每次查询都会生成100次随机分区读取,这将影响所有节点,并要求对每个节点进行单独的磁盘读取。请记住,仅仅因为您查询的是顺序索引号,并不意味着数据存储得很近,而对于Cassandra,情况恰恰相反,顺序索引号分区键可能存储在不同的节点上
您犯的第二个错误是同步执行查询(即发出查询并等待请求完成,然后再发出任何查询)。您要做的是使用线程池,以便可以并行运行多个查询,或者在单个线程中使用executeAsync方法。由于您的查询效率低下,等待100次随机分区读取完成将是一个漫长的等待过程,并且将占用大量高度流水线化的Cassandra容量如果你想最大限度地提高性能,你需要让所有的节点尽可能地忙碌
另一件需要研究的事情是在连接到集群时使用TokenAwarePolicy。这允许每个查询直接转到具有分区副本的节点,而不是随机节点,该节点可能必须充当协调器,并通过额外的跃点获取数据。当然,在读取时使用一致性级别1比使用一致性级别1更快更高的一致性级别
行缓存大小和堆大小不是问题的根源,因此这是一条错误的路径。我已经尝试了您的建议。我更改了代码,如-for(int c=0;cBATCH
你的id查询并将它们一起发送给Cassandra,但是BATCH
也不知道是否有性能。