Recently we had to deal with several customers support requests about slow queries in RavenDB. Now, just to give you some idea about the scope. We consider a query slow if it takes more than 50ms to execute (excluding client side caching).
In this case, we had gotten reports about queries that took multiple seconds to run. That was strange, and we were able to reproduce this locally, at which point we were hit with a “Duh!” moment. In all cases, the underlying issue wasn’t that the query took a long time to execute, it was that the result of the query was very large. Typical documents were in the multi megabyte ranges, and the query returned scores of those. That means that the actual cost of the query was just transporting the data to the client.
Let us imagine that you have this query:
session.Query<User>() .Where(x => x.Age >= 21) .ToList();
And for some reason it is slower than you would like. The first thing to do would probably be to see what is the raw execution times on the server side:
RavenQueryStatistics queryStats; session.Query<User>() .Customize(x=>x.ShowTimings()) .Statistics(out queryStats) .Where(x => x.Age > 15) .ToList();
Now you have the following information:
- queryStats.DurationMilliseconds – the server side total query execution time
- queryStats.TimingsInMilliseconds – the server side query execution time, per each distinct operation
- Lucene search – the time to query the Lucene index
- Loading documents – the time to load the relevant documents from disk
- Transforming results – the time to execute the result transformer, if any
- queryStats.ResultSize – the uncompressed size of the response from the server
This should give you a good indication on the relative costs.
In most cases, the issue was resolved by the customer by specifying a transformer and selecting just the properties they needed for their use case. That transformed (pun intended) a query that returned 50+ MB to one that returned 67Kb.