Sun 29 Jan 2006
There are two ways of selecting a list of objects in NHibernate based on a set of criteria.
One is using the IQuery interface which let you build a query using a sql like syntax. The other is using the ICriteria interface, which is a more object oriented way of creating a query.
I like the ICriteria way much more, but I found out that IQuery is much better in terms of performance.
I am working on a small project for a client that wants a website for engine tuning enthusiasts. I found out that the some of the pages that included searches were loading quite slowly, so I decided to try to optimize the performance.
I was using ICriteria and as an example I will show you how I filtered by a specific brand and ordered the result:
ICriteria crit = session.CreateCriteria(typeof(Car));
SimpleExpression exp1 = Expression.Eq(”Brand”, brand);
crit.Add(exp1);
Order order = Order.Desc(”HorsePower”);
crit.AddOrder(order);
IList carList = crit.List();
With the Expression-class you can create different comparisons, Gt/Like/Lt etc. and the order can of course also be ascending. I think it’s an elegant way of creating a query.
But then I tried to use IQuery instead, which in this example would be:
string q = String.Format(”from Car where BrandId = {0} order by {1} desc”, brand.Id, “HorsePower”);
IQuery query = session.CreateQuery(q);
IList carList = query.List();
This is much more SQL-like and to be honest I don’t want to be preoccupied with placing where’s and order by’s in a string, especially when there are many parameters and not all of them always are set.
But well it turns out that the search was 4-5 times quicker using IQuery.
It says in the description for ICriteria that it’s still an experimental API, so that’s probably why, but I’m a bit unhappy it’s performing that bad.
October 11th, 2006 at 7:58 pm
[…] My blog has moved. You can read the post here: NHibernate: IQuery or ICriteria […]
August 22nd, 2007 at 1:49 am
I don’t think it’s reasonable to just say it performed 4-5 times as badly without at least checking what SQL was being issued. Ultimately these 2 techniques are just different ways of constructing what amounts to an SQL statement. Check the SQL statement and see what happened. There’s nothing about ICriteria that can perform slower except the resulting SQL that is issued.
August 22nd, 2007 at 8:37 am
Thanks for your comment PandaWood.
I admit that my testing of it was not very exhaustive, but I also think that the example I used was pretty simple, so there shouldn’t be so many ways of constructing the SQL behind.
What Ayende pointed out in a comment here: http://david.givoni.com/blog/?p=25 was that it might have been the mapping that could have caused a worse SQL outcome in the ICriteria case.
I haven’t had time to try this out again, but I will try to do it soon, to get more conclusive data.
February 14th, 2008 at 10:05 pm
I am writing unit tests hitting a single isolated table (simple select) concurrently in an attempt to replicate multiple users / high load and have found that ICriteria is indeed much slower.
It also seems to not be all that thread safe. I get random load errors (ICriteria returns null)as I approach 100 threads (each thread attempts to load a record in the table).
Compare this to the typical Session.Load(typeof(…)); method of returning data, which is consistently passing with 5000 threads.
December 9th, 2009 at 4:56 pm
As far as I know, many Expression (derived from Restriction) static methods (Like, Eq, Gt, …) use an “object value” parameter, meaning they go boxing your Car to Object everytime you add a single criterion to you query. It takes time.
This may be involved in you 4/5 factor.