IsEmpty + FindSet or just FindSet?

A few days ago, I got pointed to this question on LinkedIn: https://www.linkedin.com/posts/alexander-drogin-0635422b_hey-business-central-developers-im-looking-activity-7231695259485839362-n670?utm_source=share&utm_medium=member_desktop

Or in other words:  Is it a good practice to first test of a set is empty, to then get the set of records?

I had a few thoughts:
First, I was like: duh.  Stupid question.  2 SQL roundtrips in stead of 1 is always to be avoided.  So just do only FindSet.
Second, I realized: You’re right!  I have come across this as well, multiple times.  People actually do this.
Then, I remembered the unexplained phenomenon on the JIT loading in terms of partial records, where JIT loading seems to consistently perform faster, than a full FindSet without SetLoadFields (so, no partial records).

Or in other words: 2 statements can be faster than 1.

Say what?

Ok, you don’t remember?  Well, here, in my session on BCTechDays, I explained some more on how I test “Partial Records”:

I might not have specifically addressed the JIT Load during the session (I simply forgot 🙈), but look at this:

The JIT Load was faster than one individual partial FindSet on the same table.

The JIT Load basically look liked this:

You can see in the loop I’m using a field that was not loaded in SetLoadFields.  You’ll see SQL Server performing a full SELECT (all columns, all joins to all companion tables) – and still – it performed faster.

I have no explanation.  But in any case – that has been very consistent throughout the versions.

Like today, I tested the very same code on a 24.3 sandbox in the cloud

This picture not only proves the clear and obvious performance gain since v23 thanks to the merged companion tables – but also still the same phenomenon on the JIT Load.

Still don’t believe me?

From the same data, you’ll see that the reads are all the same:

And the JIT Load indeed causes extra SQL Statements:

OK .. but what does this have to do with the current topic?

Well – it made me think – may be people ARE doing the IsEmpty + FindSet for a good reason, and I’m wrong.  May be IsEmpty + FindSet is better than *just* FindSet, like it seems to be with JIT Loading.

So – I wanted to check…

The Testcase

I must say – it was easier said than done to come up with meaningful durations.  Most of my cases had 1 thru 4 milliseconds – even for sets of 500k records.  So, I just decided to read multiple tables, to amplify the impact a bit.

The first function,  I pretty much read 5 tables, first with IsEmpty, second the FindSet, with a weird filter:  No magic at all:

In the second function, I took the “IsEmpty” out:

In a third, I would only execute the IsEmpty .. just because I could:

And I must say – the results were not that surprising this time :-).  Completely expected behavior.

As expected, the extra IsEmpty causes more SQL Statements:

And it takes longer (also as expected):

Conclusion

If you’re an IsEmpty-before-FindSet-kind-of-guy/girl: please stop it, or step away from your keyboard 😜.

5.00 avg. rating (99% score) - 8 votes

Permanent link to this article: https://www.waldo.be/2024/08/23/isempty-findset-or-just-findset/

5 comments

Skip to comment form

    • Morten Sorlie on August 23, 2024 at 1:07 pm
    • Reply

    Interesting…
    Note that IsEmpty also forces a table lock.
    Therefore, use it together with ReadIsolation.

    • Matt on September 14, 2024 at 5:30 pm
    • Reply

    IsEmpty is still good to use before a DeleteAll call. More SQL calls but an empty delete all has a very negative performance impact.

    • Kishor Mistry on October 22, 2024 at 12:02 pm
    • Reply

    Just one thing came to mind – your results are only valid if you have data in the table every time. If say 50% of the time IsEmpty returned true then you could skip the FindSet 50% of the time which would mean that the IsEmpty + FindSet combination would be better than just FindSet overall

      • waldo on October 29, 2024 at 4:42 pm
        Author

      I don’t agree, sorry.

      first of all: What does it mean “50% the table is empty”? How can a table be empty half of the time? What kind of table is that?
      Second: I’m talking guidelines here. I’d rather gamble for the “other” 50% to not go to the “big” table twice, than the incredible limited time that is gained by doing an IsEmpty first.. 🤷‍♂️.

      Just my 2 cents..

      • Kishor Mistry on October 29, 2024 at 5:39 pm

      I should have said “50% of the time the result set is empty” – for example you may be applying a filter on the “Reservation Entry” table and this would usually be with specific filters. Now although the table is rarely ever empty, the result set after filtering for a specific related record may quite often be empty (e.g. you want to loop through all Reservation Entry records for each Sales Line on a Sales Order). If only 5 out of 10 of the sales lines on an order typically have reservations then 50% of the time the result set is empty.

      I agree there is no hard and fast rule, I was just saying that there may be cases where you don’t expect to have a non-empty result set most of the time and if this is the case then having an empty before a findset may be beneficial.

      If you do normally expect a non-empty result set then I agree there is no point having an IsEmpty before the FindSet

      P.S. my original post may have come across a bit harsh, I didn’t mean that your blog/result were incorrect, just that it really depend on whether you normally expect a (non-empty) result set or not

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.