OPATH
is the basic syntax used for PowerShell queries. It is similar in
concept to but uses different syntax from Lightweight Directory Access
Protocol (LDAP) queries. Dynamic distribution groups also use OPATH queries to locate objects in Active Directory when the
transport system builds addressee lists to deliver message addresses to
these groups.
8. Server-side and client-side filters
Windows PowerShell supports server-side and client-side
filters. There’s a big difference in performance between the two types
of filters, especially when you have to process more than a hundred
objects. Client-side filters are the default. Any code that uses the
Where cmdlet executes a client-side filter. Client-side filters request
data from a server and then perform the filtering on the client. This
is an effective approach if you only have 10 or 15 objects to process,
but it obviously doesn’t scale too well as the number of objects
increases.
Server-side filters have better scalability because
the request for data forces the server to return a filtered data set to
the client. Because Exchange servers often have to deal with tens of
thousands of objects, a number of the Exchange cmdlets support
server-side filters. If a cmdlet supports the –Filter parameter, it
supports server-side filters. Usually, these are cmdlets that deal with
objects that output large numbers, such as mail-enabled recipients or
message queues. All the precanned filters generated for dynamic
distribution groups, address lists, and email address policies use
server-side filters.
As an example of server-side and client-side
filtering in action, two methods are available to find all the
mailboxes with “James” in their name, as demonstrated in these commands:
Get-Mailbox –Filter {Name –like '*James*'} –ResultSize 5000
Get-Mailbox –ResultSize 5000 | Where {$_.Name –like '*James*'}
On
the surface, these two pieces of code seem reasonably similar, but they
are very different in reality. The first difference is that the first
code example uses a server-side filter, and the second uses a
client-side filter. The second difference is that the two filter types
can generate very different results because of the way the filters
operate. If you omit the –ResultSize parameter, the same query is
generated: Find all the mailboxes with a name that contains “James.”
(The ResultSize parameter in the first example limits the total number
of objects returned to 5,000.) However, if you time both queries, the
server-side filter invariably executes faster than the client-side
filter, largely because fewer data are transferred between server and
client. To understand why the filters generate different results, you
have to appreciate how the filters work:
The server-side filter returns the first 5,000 mailboxes it finds that include “James” in the mailbox name.
The
client-side filter fetches data for the first 5,000 mailboxes and then
applies the filter to find the mailboxes that include “James” in the
mailbox name. However, the filter applies only to the set the client
fetched and might not find all the mailboxes you actually want to
discover.
Even though you ask the server-side
filter to do more work (working with any reasonably sized set of
mailboxes, the server-side filter will have to process significantly
more data to find the first 5,000 mailboxes that match), it still
executes faster. For example, when I executed similar commands within a
very large Exchange organization (170,000 mailboxes), the server-side
filter completed processing in 43 seconds, whereas the client-side
filter completed in 81 seconds. The rule here is that the effect of
server-side filtering gets better as the number of objects increases.
Sometimes
people make the mistake of assuming that client-side filters are faster
because server-side filters provide the data in one motion after the
server processes all the data. You therefore wait for a while without
seeing anything and then see all the filtered records at one time. By
comparison, client-side filters fetch and filter data continuously, so
you see output as the command finds each matching record. However, the
important indicator of performance is how long each type of filter
takes to complete, and server-side filters are always faster.
The commands you are most likely to use with server-side filters are as follows:
Get-User. Retrieve basic Active Directory properties for any user account, including mail-enabled accounts.
Get-Mailbox. Retrieve Exchange-specific properties for mailboxes.
Get-DistributionGroup. Retrieve Exchange-specific properties for mail-enabled groups.
Each
of the commands you can use to work with user accounts, groups, and
mailboxes supports a different set of filterable properties. To
discover which properties are available for filtering, you can use
PowerShell to query the properties of a returned object. For example:
Get-Mailbox -Identity Redmond | Get-Member | Where-Object {$_.MemberType –eq 'Property'} |
Sort-Object Name | Format-Table Name
This
set of commands calls a command to return some information about an
object. It then pipes the information returned by the first command to
the Get-Member cmdlet, which extracts information about the properties.
You sort the properties by name and output them in table format. Here’s
an excerpt from the output:
Name
----
AcceptMessagesOnlyFrom
AcceptMessagesOnlyFromDLMembers
AddressListMembership
Alias
AntispamBypassEnabled
CustomAttribute1
CustomAttribute10
…
WindowsEmailAddress
This
method works for the Get-Mailbox, Get-CASMailbox, Get-User,
Get-Recipient, Get-DistributionGroup, and Get-DynamicDistributionGroup
cmdlets. You can use any of the values reported in a –Filter statement.
For instance, the call you just made to Get-Mailbox reports that the
custom attributes are available, so to find all mailboxes that have a
value in the CustomAttribute10 property, you can generate a command
like this:
Get-Mailbox –Filter {CustomAttribute10 –ne $Null}
If
you look at the filterable properties reported by the
Get-DynamicDistributionGroup cmdlet, you can see that the ManagedBy
property is available for this dynamic distribution group, whereas it
is not for mailboxes. Hence, you can execute a filter like this:
Get-DynamicDistributionGroup –Filter {ManagedBy –ne $Null}
When
you create a filter, it is best to be as specific as possible. You can
state several conditions within a filter. An example of a server-side
filter that returns all the mailboxes in the Dublin office where the
user name contains “Tony” is shown next. The Get-User cmdlet also works
with this filter, but Get-Mailbox executes a tad faster because the
server does not have to process accounts that are not mail-enabled.
Get-Mailbox –Filter {Office –eq 'Dublin' –and Name –like '*Tony*'}
After
you have mastered server-side filtering, you will use it all the time
to work with sets of users. For example, assume that you want to give a
new mailbox quota to members of a certain department but no one else.
Get-User –Filter {Department –Eq 'Advanced Technology'} | Set-Mailbox
–UseDatabaseQuotaDefaults:$False
–IssueWarningQuota 5000MB –ProhibitSendQuota 5050MB –ProhibitSendReceiveQuota 5075MB