views:

289

answers:

4

We're still evaluating Cassandra for our data store. As a very simple test, I inserted a value for 4 columns into the Keyspace1/Standard1 column family on my local machine amounting to about 100 bytes of data. Then I read it back as fast as I could by row key. I can read it back at 160,000/second. Great.

Then I put in a million similar records all with keys in the form of X.Y where X in (1..10) and Y in (1..100,000) and I queried for a random record. Performance fell to 26,000 queries per second. This is still well above the number of queries we need to support (about 1,500/sec)

Finally I put ten million records in from 1.1 up through 10.1000000 and randomly queried for one of the 10 million records. Performance is abysmal at 60 queries per second and my disk is thrashing around like crazy.

I also verified that if I ask for a subset of the data, say the 1,000 records between 3,000,000 and 3,001,000, it returns slowly at first and then as they cache, it speeds right up to 20,000 queries per second and my disk stops going crazy.

I've read all over that people are storing billions of records in Cassandra and fetching them at 5-6k per second, but I can't get anywhere near that with only 10mil records. Any idea what I'm doing wrong? Is there some setting I need to change from the defaults? I'm on an overclocked Core i7 box with 6gigs of ram so I don't think it's the machine.

Here's my code to fetch records which I'm spawning into 8 threads to ask for one value from one column via row key:

ColumnPath cp = new ColumnPath(); cp.Column_family = "Standard1"; cp.Column = utf8Encoding.GetBytes("site"); string key = (1+sRand.Next(9)) + "." + (1+sRand.Next(1000000)); ColumnOrSuperColumn logline = client.get("Keyspace1", key, cp, ConsistencyLevel.ONE);

Thanks for any insights

A: 

It looks like you haven't got enough RAM to store all the records in memory.

If you swap to disk then you are in trouble, and performance is expected to drop significantly, especially if you are random reading.

You could also try benchmarking some other popular alternatives, like Redis or VoltDB.

the_void
We definitely can't fit them all in memory, but 10mil records doesn't seem like a lot. How are people dealing with billions of records??
Jody Powlette
The key is to keep as much as possible in RAM, not on disk. To handle billions of records you would distribute them across multiple machines and use them as a whole. Here's a very nice article [1] on how this is achieved in Riak, another popular NoSQL solution. Many of the aspects discussed in the article also apply to Cassandra, as they are build on the same fundamental ideas.[1]: https://wiki.basho.com/display/RIAK/An+Introduction+to+Riak
the_void
+1  A: 

purely random reads is about worst-case behavior for the caching that your OS (and Cassandra if you set up key or row cache) tries to do.

if you look at contrib/py_stress in the Cassandra source distribution, it has a configurable stdev to perform random reads but with some keys hotter than others. this will be more representative of most real-world workloads.

jbellis
Unfortunately we'll have random visitors arriving to our site at random intervals - there's no distribution that we'll know ahead of time to get more cache hits. Are we simply limited to disk speed in this case?
Jody Powlette
Nothing is truly random. Your real-life performance is very likely to be better than your tests. That being said, is Cassandra actually using up all of the memory on the box? 60 reads/sec is so horrible on your hardware that it's likely you have a setup problem (well, depending on how awful your disks are). Also, make sure Cassandra isn't using swap as if it were physical memory - that creates a pathological performance problem with both Cassandra and the OS independently trying to optimize in-memory pages in competing ways.
Nick Bastin
A: 

Add more Cassandra nodes and give them lots of memory (-Xms / -Xmx). The more Cassandra instances you have, the data will be partitioned across the nodes and much more likely to be in memory or more easily accessed from disk. You'll be very limited with trying to scale a single workstation class CPU. Also, check the default -Xms/-Xmx setting. I think the default is 1GB.

Todd
A: 

VoltDB can certainly handle this level of read performance as well as writes and operates using a cluster of servers. As an in-memory solution you need to build a large enough cluster to hold all of your data in RAM.

tmcallaghan