2013-12-12 62 views
1

我有一个包含1MB blob的表。范围查询期间的Cassandra OutOfMemoryError

CREATE TABLE blobs_1( 关键文本, 版本BIGINT, 块INT, object_blob一滴, object_size INT, PRIMARY KEY(键,版本,块) )

每个LOB散布关于100块。 以下查询导致OutOfMemory错误:

从blobs_1中选择object_size,其中key ='key1'和version = 1;

以下是错误:

java.lang.OutOfMemoryError:Java堆空间 在org.apache.cassandra.io.util.RandomAccessReader.readBytes(RandomAccessReader.java:344) 在org.apache。 cassandra.utils.ByteBufferUtil.read(ByteBufferUtil.java:392) 在org.apache.cassandra.utils.ByteBufferUtil.readWithLength(ByteBufferUtil.java:355) 在org.apache.cassandra.db.ColumnSerializer.deserializeColumnBody(ColumnSerializer。 java:124) at org.apache.cassandra.db.OnDiskAtom $ Serializer.deserializeFromSSTable(OnDiskAtom.java:85) at org.apache.cassandra.db.Column $ 1.computeNext(Column的.java:75) 在org.apache.cassandra.db.Column $ 1.computeNext(Column.java:64) 在com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143) 在COM。 google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138) at org.apache.cassandra.db.columniterator.SimpleSliceReader.computeNext(SimpleSliceReader.java:88) at org.apache.cassandra.db.columniterator。 SimpleSliceReader.computeNext(SimpleSliceReader.java:37) com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143) com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138) at org.apache.cassandra.db.columniterator.SSTableSliceIterator.hasNext(SSTableSliceIterator.java:82) 在org.apache.cassandra.db.columniterator.LazyColumnIterator.computeNext(LazyColumnIterator.java:82) 在org.apache.cassandra.db.columniterator.LazyColumnIterator.computeNext(LazyColumnIterator.java:59) 在com.google。 com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138) (org.apache.cassandra.db.filter.QueryFilter $ 2.get) (QueryFilter.java:157) at org.apache.cassandra.db.filter.QueryFilter $ 2.hasNext(QueryFilter.java:140) at org.apache.cassandra.utils.MergeIterator $ Candidate.advance(MergeIterator.java: 144) at org.apache.cassandra.utils.MergeIterator $ ManyToOne.advance(MergeIterator.java:123) at org .apache.cassandra.utils.MergeIterator $ ManyToOne.computeNext(MergeIterator.java:97) at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143) at com.google.common.collect.AbstractIterator .hasNext(AbstractIterator.java:138) at org.apache.cassandra.db.filter.SliceQueryFilter.collectReducedColumns(SliceQueryFilter.java:185) at org.apache.cassandra.db.filter.QueryFilter.collat​​eColumns(QueryFilter.java :122) 在org.apache.cassandra.db.filter.QueryFilter.collat​​eOnDiskAtom(QueryFilter.java:80) 在org.apache.cassandra.db.RowIteratorFactory $ 2.getReduced(RowIteratorFactory.java:101) 在有机apache.cassandra.db.RowIteratorFactory港币$ 16。getReduced(RowIteratorFactory.java:75) at org.apache.cassandra.utils.MergeIterator $ ManyToOne.consume(MergeIterator.java:115) at org.apache.cassandra.utils.MergeIterator $ ManyToOne.computeNext(MergeIterator.java: 98)

+0

这发生在2.0.2上。令人沮丧的是,单个查询如此轻易地崩溃了服务器。 – user3025533

回答

0

发生此错误是因为Cassandra在读取表的单个列(至少Cassandra 1.2,也许这已在2.0分支中得到改进)时反序列化了超出必要的数据。

要解决这个问题,你可以引入一个单独的元数据表(尺寸等)。它会减慢写入的速度,但会大大提高读取性能。

2

您需要减少页面大小。默认分页大小适用于普通的小列/行。对于大块,您需要缩小分页大小。

https://github.com/datastax/java-driver/blob/2.0/driver-core/src/main/java/com/datastax/driver/core/Statement.java#L234

+0

我也创建了https://issues.apache.org/jira/browse/CASSANDRA-6492来自动执行此操作。 – jbellis

+0

因为这发生在cqlsh中,所以java驱动程序不会有太大的帮助。那么,如果我只需要object_size,就没有办法避免抓取blob了?我可以将“object_size”移动到另一个表中,但是当我试图获取作为主键一部分的“块”时会发生同样的问题,并且这不能移动到另一个表中。 – user3025533