Some Complexities to Consider When Upgrading Scripts

Last month, I wrote about upgrading Exchange Online PowerShell scripts to use the Get-ExoMailbox cmdlet instead of its older Get-Mailbox counterpart. One of the reasons I advanced is that Get-ExoMailbox is faster at retrieving mailbox data, which led to some questions about performance in general. It’s easy (and quick) to fetch data for a few mailboxes, but once you need to deal with hundreds or thousands of mailboxes, it’s important to optimize.

Filtering Data

Which brings me to the topic of filters. It’s common to need to process just a few mailboxes of the full set available in a tenant. Filters apply conditions for PowerShell to select the right mailboxes. The better the filter, the faster you get the mailboxes you want.

Filters come in two variants: server-side and client-side. Server-side means that the data coming back from the server is filtered and ready to go. Client-side means that data comes down from the server and is filtered on the client. Generally speaking, for best performance, the golden rule is to use server-side filtering whenever possible.

Server-side filtering happens when the Filter parameter passes a query against mailbox properties to the server. Exchange PowerShell supports a wide range of filterable properties which can be used with its cmdlets. For example, this command returns mailboxes with the Office property set to Dublin.

The equivalent client-side filter fetches all mailboxes and pipes the set to a Where command to filter out the desired mailboxes:

At first glance, you’d expect this code to work because the approach works with Get-Mailbox. But it doesn’t because the Office property is not in the default property set returned by Get-ExoMailbox. Remember, part of the reason why the REST cmdlets are faster than their Remote PowerShell counterparts is the reduction in the number of properties they return. To make our code work, we must tell Get-ExoMailbox to fetch the Office property.

You don’t have to worry about specifying properties when you use server-side filtering because Exchange applies the filter on the server. The property restriction only applies for data returned to the client.

Remember that other parameters cause filtering to happen on the server too. Combining these parameters together creates an even more precise query. In this example, we add the RecipientTypeDetails parameter to instruct Exchange Online to return only user mailboxes:

Specifying the number of objects to be returned is also another form of filter:

The critical point is to be as specific as possible in requesting data from the server. This will speed processing up and mean that you don’t need to discard information when it gets to the client.

Inconsistencies in Filters

A couple of inconsistencies exist in the way that server-side filtering happens for the new cmdlets. For example, you need to be careful with wildcards. Microsoft’s documentation says:

The -like and -notlike operators are limited in using wildcards (*). Specifically, you can only use wildcards at the beginning of a string value, at the end of a string value, or both.

This text makes it seem like you could take a command like this:

And upgrade it to use Get-ExoMailbox instead:

But the command fails with an invalid filter clause, which proves the need for testing even when a statement in Microsoft documentation gives reassurance that something should work.

Reversing Advice

For years, people have applied the golden rule to use server-side filtering to fetch mailbox data. But as we’ve just seen, the REST-based cmdlets do not work in the same way as the older cmdlets. In fact, the Exchange Online development team found that client-side filtering is faster for the new cmdlets, including Get-ExoMailbox. Microsoft says that they’re working on improving server-side filtering for the cmdlets.

After running some tests, it seems like the cause for Microsoft’s assertion is the way that Get-ExoMailbox needs to “warm up” when finding mailboxes. This includes preparing for result pagination, connecting to mailbox servers, and so on. The effect of warming up is easily seen by running the same query multiple times. The first run is always slowest and runs thereafter are much faster, and is easily verified using the Measure-Command cmdlet to run a command several times.

However, with an eye on future performance improvements, I’m not sure that I want to follow Microsoft’s recommendation to use client-side filtering with Get-ExoMailbox. The performance penalty at present doesn’t seem excessive and staying with server-side filtering avoids the need for further change in the future. However, this theory must be tested in the context of individual scripts. For some, it will be best to convert to client-side filtering, for others, the best decision is to stay as is.

Source Practical365

Chioma Ugochukwu

The author Chioma Ugochukwu

Leave a Response