Permalink
Find file
59e0ad0 Aug 17, 2014
78 lines (55 sloc) 7.06 KB

NoSQL and RDBMS – Choose your weapon.

nosql_thumb Sensationalist headline right? Unfortunately I think the aggressive tone of the term ‘NoSQL’ is one of the reasons that a lot of people have an instant resentment to the technology. It encourages flame ignited posts like http://teddziuba.com/2010/03/i-cant-wait-for-nosql-to-die.html which when posted to Slashdot will get every developer who has ever touched an RDBMS to weigh-in and pass judgement on technology that they’ve never used before in a combined post also declaring their eternal love for their preferred RDBMS of choice.

The negative posts generally share the same tone:

I have developed with RDBMS for 10 years and I’ve never needed to use a NoSQL database. RDBMS can scale just as good as NoSQL.

Unfortunately statements like the above instantly illustrate the developer has a biased attachment to a technology they’ve used all their life whilst at the same time declare they have absolutely no knowledge (or desire to gain any knowledge) on the subject for which they are passing judgement. It’s most likely these developers have also made message queues fit in databases and marvelled at their configuration-mapping ability to have an eagerly-loaded chain of nested objects auto-magically bind to their pristine domain model. Yes this is quite a feat to be proud of, unfortunately it also happens to be a one-liner in a lot of non-relational databases. This characteristic of being able to serialize your domain model without requiring it to be mapped to a database using an ORM is not a feature limited to NoSQL databases, other data persistence solutions like db4o (an object orientated database) achieve this equally as well.

Picking the best tool for the job?

All this says is that RDBMS’s are really good at doing what they do, which is storing flat, relational, tabular data. Now believe it or not they still remain the best solution for storing relational data. Using a NoSQL data store isn’t an all-or-nothing technology. It is actually serves as a good complementary technology to have along-side an RDBMS. Yes that’s right even though they have overlapping feature-set they can still be great together. Awesome – we can all still be friends!

It’s still all about picking the right tool and using the right technology for the task at hand. Which leads me to what NoSQL databases are naturally good at:

  • Performance – As everything is retrieved by key, effectively all your queries hits an index. Redis an in-memory data-store (with optional async persistence) can achieve 110000 SETs/second, 81000 GETs/second in an entry level Linux box, and no this is not possible with any RDBMS.
  • Replication – A feature common in most NoSQL data stores is effortless replication. In Redis this is achieved by un-commenting one line: ‘slaveof ipaddress port’ in redis.conf
  • Schema-less persistence – As there is no formal data structure to bind to and most values are stored as binary or strings the serialization format is left up to you. Effectively this can be seen as a feature as it leaves you free to serialize your object directly – which lets you do those one-liner saves that everyone is talking about. A lot of client libraries opt for a simplistic language-neutral format like JSON.
  • Scalability – This seems to be a heated topic (where everyone believes they can scale their technology of choice equally as well given the right setup) so I won’t delve in to this too deeply only to say that key-value data-stores by their nature have good characteristics to scale. When everything is accessed by key, clients can easily predict the source of data given a pool of available data-stores. Most clients also come in-built with consistent hashing where the addition or removal of a data store does not significantly impact this predictability.
  • Efficiency and Cost – As there are a plethora of options available most NoSQL data stores are both free and open source. They also perform better and provide better utilization of server resources than comparative RDBMS solutions.
  • Advanced data constructs – NoSQL variants like Redis, in addition to a key-value data store also provide rich data constructs and atomic operations on server-side lists, sets, sorted sets and hashes which make things like message-queuing, notification systems, load-balancing work tasks trivial to implement.

Try NoSQL today

redis Fortunately NoSQL solutions are not black magic and are actually fairly easy to get started with. My personal favourite is Redis for which I also happen to be the maintainer of a rich open source C# client (can also run on Linux with Mono). If .NET is not your thing, than you’re in luck as Redis is so popular that there is a language binding in almost every programming language in active use today which you can find listed on its supported languages page.

Getting started is as easy as downloading the latest source from the project website. If you’re on a windows platform you can download pre-compiled binaries using cygwin here. A simple make command from the tarball directory creates the required redis-server which is all you need to run to get a server instance up and running.

After that you can access the comprehensive Redis feature-set exposed by the C# IRedisClient API. To give you a taste of it’s simplicity, here is an example demonstrating how to persist and access a simple POCO type using the Redis client:

public class IntAndString
{
        public int Id { get; set; }
        public string Letter { get; set; }
}

using (var redisClient = new RedisClient())
{
        //Create a typed Redis client that treats all values as IntAndString:
        var typedRedis = redisClient.GetTypedClient<IntAndString>();

    var pocoValue = new IntAndString { Id = 1, Letter = "A" };
        typedRedis.Set("pocoKey", pocoValue);
        IntAndString toPocoValue = typedRedis.Get("pocoKey");

        Assert.That(toPocoValue.Id, Is.EqualTo(pocoValue.Id));
        Assert.That(toPocoValue.Letter, Is.EqualTo(pocoValue.Letter));

        var pocoListValues = new List<IntAndString> {
                new IntAndString {Id = 2, Letter = "B"},
                new IntAndString {Id = 3, Letter = "C"},
                new IntAndString {Id = 4, Letter = "D"},
                new IntAndString {Id = 5, Letter = "E"},
        };

        IRedisList<IntAndString> pocoList = typedRedis.Lists["pocoListKey"];

        //Adding all IntAndString objects into the redis list 'pocoListKey'
        pocoListValues.ForEach(x => pocoList.Add(x));

        List<IntAndString> toPocoListValues = pocoList.ToList();

        for (var i=0; i < pocoListValues.Count; i++)
        {
                pocoValue = pocoListValues[i];
                toPocoValue = toPocoListValues[i];
                Assert.That(toPocoValue.Id, Is.EqualTo(pocoValue.Id));
                Assert.That(toPocoValue.Letter, Is.EqualTo(pocoValue.Letter));
        }
}

Other note-worthy features of Redis include its support for custom atomic transactions examples of which are here.

More examples are available at the ServiceStack’s Open source C# Client’s home page.