Sitecore and FxCop – ItemAxes and Database Rules

This is the fourthpost in the Sitecore and FxCop series

I’ve been working on a bunch of easier to implement rules, which I figured I’d run through here. As always, I’m trying to improve the code, either increasing the performance of the code or making it a little more safe to use.

There’s a couple of categories in which I’ve added rules, and I’ll be creating a post per category, as it’ll be a huge post otherwise.

The categories I added rules in are:

ItemAxes & Database

This is one of the most important areas for performance issues. When we are using the ItemAxes to get all ancestors or descendants that can take a very big performance hit. It is often much better and faster to use Sitecore.ContentSearch (granted, this can only be done using Sitecore 7 and up). The same goes for the SelectItems() with Xpath as well.

So the four rules I put in on the ItemAxes are:

  1. Don’t use SelectSingleItem (accessible as Sitecore.Data.Items.ItemAxes.SelectSingleItem as well as Sitecore.Data.Database.SelectSingleItem)
  2. Don’t use SelectItems (accessible as Sitecore.Data.Items.ItemAxes.SelectItems as well as Sitecore.Data.Database.SelectItems)
  3. Don’t use GetAncestors
  4. Don’t use GetDescendants

On this blogpost I saw some stats for Lucene and fast query, which is not really a fair comparison I think because fast query will always go straight to the database, I figured I’d get a bit of data together.

Consider the following code:

var index = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index")
{
    using (var context = index.CreateSearchContext())
    {
        // ContentSearch
        Stopwatch sw = new Stopwatch();
        sw.Start();
        var indexed = context.GetQueryable<Sitecore.ContentSearch.SearchTypes.SearchResultItem>().Where(item => item.Name.Contains("s"));
        sw.Stop();
        Sitecore.Diagnostics.Log.Info(string.Format("ContentSearch. Elapsed time: {0}. Items found: {1}", sw.Elapsed, indexed.ToList().Count));
    }

    // Fast query
    Stopwatch sw2 = new Stopwatch();
    sw2.Start();
    var fQuery = Sitecore.Configuration.Factory.GetDatabase("master").SelectItems("fast://*[@@name='%s%']");
    sw2.Stop();
    Sitecore.Diagnostics.Log.Info(string.Format("Fast query. Elapsed time: {0}. Items found: {1}", sw2.Elapsed, fQuery.Length), this);

    // Normal query
    Stopwatch sw3 = new Stopwatch();
    sw3.Start();
    var query = Sitecore.Configuration.Factory.GetDatabase("master").SelectItems("//*[contains(@@name, 's')]");
    sw3.Stop();
    Sitecore.Diagnostics.Log.Info(string.Format("Normal query. Elapsed time: {0}. Items found: {1}", sw3.Elapsed, query.Length), this);
}

This gave me the following output in my Sitecore log file:

INFO ContentSearch. Elapsed time: 00:00:00:0178173. Items found: 8723
INFO Fast query. Elapsed time: 00:00:05.2718443. Items found: 5194
INFO Normal query. Elapsed time: 00:00:09.7881149. Items found: 4320

Those are some pretty big differences. These results are for just under 13000 items. Of course, it’s still not completely honest because the normal query does need to call the Contains function, which I don’t know the performance implications for…

Another big plus of using ContentSearch is that Linq is a lot easier to read in more complex queries than Xpath / Fast query.

From a custom rule perspective, those four rules are extremely simple to create. Almost all rules I added to my project so far use a lot of the same code – If the corresponding classes get called, flag them as warnings on the page.

Of course, as with all rules, there’s bound to be some exceptions and actual legitimate good uses of these classes. The rules are only there to point out that it might be a good idea to re-think that.

Advertisements

3 thoughts on “Sitecore and FxCop – ItemAxes and Database Rules

  1. Is this still the case if you repeat the fast query or query versions? I noticed with my own tests that repeated calls on the Axes with the cache involved gave reasonable access times on calls 2 / 3 (repeated). Obviously pre sitecore 7 you could use Lucene.Net direct, the Advanced Search Crawler or Lucinq which would have given similar results to SC7 search.

    • This rule, as with other rules, always do have exceptions. There are valid reasons to use Sitecore query or fast query. These are just general pointers if you’re experiencing for performance issues.

      Having said that, all stats in the above example are running through the entire content tree (which I would suggest not doing in real-life scenarios) only once, I haven’t checked running it multiple times, it would make sense that caching would kick in at that point.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s