In my post the other day about my choices of technological underpinnings for my startup, TruthVine, there was one choice I omitted to mention. I didn’t say which database I had decided upon.
In fact it was a decision which took no consideration at all: having worked with RavenDb on the inside and from the outside, it was my immediate choice. Here’s why.
RavenDb stays out of the way
RavenDb is like a waiter at the best kind of restaurant. It serves your data with the minimum of fuss and gets out of the way. Unlike certain persistence technologies I could mention, there is barely any configuration involved, and not a mapping in sight. You just hand RavenDb an object or any shape or size, and RavenDb stores it. You murmur an object’s id, and RavenDb has it on your plate in an instant, child collections and all.
RavenDb is a document database. That means that you don’t need to declare a schema upfront. Whenever you hand RavenDb an object it simply serializes it to JSON format, and stores it as a blob in its persistence engine. The benefit I see from this is greatly reduced pain when deploying updates to my code, as I won’t need to worry about sql migration scripts. I can add things to my objects with impunity, and for other situations, RavenDb has very nice document patching support.
As as you’d expect, given RavenDb’s provenance, the RavenDb .Net client is awesome. It has full support for the unit-of-work pattern and transactions. Thus any entities you load within a session are tracked, and any that have changed when you save the session are sent to the database in a single transaction. Naturally, the RavenDb client has LINQ support too, with paging in queries being especially trivial to implement.
Here’s a complete snippet showing everything you need to store and retrieve objects from RavenDb.
class RavenDbDemo
{
public void Demonstrate()
{
// DocumentStore is a heavy-weight object usually created once per application
var documentStore = new DocumentStore() {Url = "http://myravendbserver.com"};
documentStore.Initialize();
// session objects are light-weight and are created per transaction
using (var session = documentStore.OpenSession())
{
var person = new Person()
{
Name = "Samuel Jack",
FavouriteDatabase = "Sql Server"
};
session.Store(person);
session.SaveChanges();
}
using (var session = documentStore.OpenSession())
{
var person = session.Query<Person>()
.First(p => p.Name == "Samuel Jack");
person.FavouriteDatabase = "RavenDb";
session.SaveChanges();
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string FavouriteDatabase { get; set; }
}
}
Indexing is largely automatic
One thing this snippet highlights is RavenDb’s awesome indexing support. Whenever you make a new kind of query, RavenDb will automatically create an index for you to query against. In the most recent versions of RavenDb, it will automatically tune the indexes over time, depending on the patterns of queries you make against the database. Of course, you can define more sophisticated indexes explicitly, but often you never need to.
One situation where you will need to create indexes is when you want to take advantage of RavenDb’s Map/Reduce support. This is how RavenDb supports queries which involve aggregating multiple documents, since it doesn’t implement grouping clauses in LINQ queries from the client. The nice thing about the way it does this is that Map/Reduce indexes are persisted just like other indexes, which makes aggregate queries very fast.
And There’s More
There is so much more to like about RavenDb, but I’ll just highlight a few other things which I think will be important to me as a startup.
The first is RavenDb’s replication support. This is important if you want to make sure your application has high availability. Configuring replication is as easy as entering the connection string for the database you want RavenDb to replicate too. Replication also helps enormously with scalability, as you can configure your clients to read from any of the replicas, thus spreading the load, but write to the master database, thus ensuring consistency without generating conflicts.
Next is backup support. RavenDb comes with built in support for doing backups to Amazon S3, or Amazon Glacier. You just have to tell it the bucket you want to write to, and your API keys, and off it goes.
The level of support available is always an important consideration when choosing to adopt a product, and RavenDb has great support, both from the RavenDb community who hang out on the RavenDb group, and from Ayende and the rest of the Hibernating Rhinos team. RavenDb is an open source project (using the AGPL license, so you must buy a license if you’re not willing to open-source your own code) and the community are very active in contributing to the project.
I should mention that, if RavenDb has one failing, the documentation is not as good as it might be. The situation has improved a lot recently, and I understand a couple of books are in progress. Most of the time RavenDb just works, but if you stray too far from the beaten path, you might find yourself relying on the community to help you understand what’s going on. Having the code available certainly helps, and, as I said, the community are very responsive.
Finally, I can’t resist a plug for the Management UI (in which, if you press me, I might admit to having played a part!).
I love the fact that you scan scroll through your entire documents collection, or through all the results of a query, with the client paging in the data as necessary.
Full disclosure: Whilst these opinions are entirely my own, and I do not believe them to be prejudiced by any other factors, I have been offered a RavenDb license by Hibernating Rhinos in exchange for setting them out in this blog post. I am also a freelance contributor to the RavenDb project.