Improving Directory Service Performance


Although directory services store a wealth of useful information, the volumes of data they contain can easily result in slow search performance. A slow directory service gives an overall impression that the application is slow. Although most directory service solutions, such as Active Directory, are scalable and improve as additional hardware is added, improvements to the search parameters can more easily address the problem. The following guidelines can significantly improve the performance of a search and, as a result, the application.

Selecting the Base Object

Improving the performance of a search has a lot to do with choosing the optimal starting point for the search. This starting point can be either the root of the hierarchy, an object entry, or a container. One-level searches on a container are faster than subtree searches over the entire hierarchy. When you know the name of the container where the object is, use the name of the container and perform a one-level search. After you find the object, bind to the object using its name to access its attributes:

 public void ConnectToSpecificUser() {     //connect as close as possible to target object     String strConnection = "LDAP://srv-enterprise/CN=User/UID=alyssa";     DirectoryEntry direntry = new DirectoryEntry( strConnection );     return; } 

Specifying Search Scope

The scope of a search also impacts performance. You can select three scopes for a search: base, one level, and subtree. The base scope is the fastest scope to use for retrieving a single object. The one-level scope is the fastest way to retrieve multiple objects. When the objects are located in a single known container, you should use the one-level scope to return the attributes for one or more objects. The subtree scope retrieves data from multiple containers. When you need to return the attributes for one or more objects contained in multiple containers in the same hierarchy, you should use the subtree scope

Querying Only the Attributes Needed

When performing a search, specify only the attributes needed in the returned results. By default, all attributes associated with an object are returned. The fewer attributes that need to be loaded, the faster the results can be built and returned. This is where the PropertiesToLoad property becomes handy. In this example, only the givenname and sn attributes are necessary to build a user list. To increase performance, only those properties are requested :

 public void RetrieveSpecificData() {     String strConnection = "LDAP://srv-enterprise/CN=User";     //establish connection to base object     DirectoryEntry dirEntry = new DirectoryEntry( strConnection );     DirectorySearcher dirSearcher = new DirectorySearcher( dirEntry );     //search for the specific user     dirSearcher.Filter = "(&(objectClass=User)(cn=\"Lonnie Scully\"))";     dirSearcher.SearchScope = SearchScope.Subtree;     //specify the data to retrieve     dirSearcher.PropertyNamesOnly = true;     dirSearcher.PropertiesToLoad.Add( "givenname" );     dirSearcher.PropertiesToLoad.Add( "sn" );     //perform the search     SearchResult searchResult = dirSearcher.FindOne();     return; } 

Minimizing Partial String Searches

Although the directory service has powerful support for partial string matches, it is time consuming. If partial matches are necessary, place the wildcard character at the end of the search string, rather than the beginning. A query, such as (cn=alyssa*) performs much faster than (cn=*lyss*) or (cn=*lyssa) .

Querying Objects Once

When reading attributes from a directory service object, such as a User object, load all attributes at once and store them locally. This way, you can retrieve attributes more quickly than retrieving a number of attributes from the directory service a little at a time:

 class UserData {     string _Lastname = "";     string _Firstname = "";     public void GetUserFullName()     {         String strConnection = "LDAP://srv-enterprise/CN=User";         //establish connection to base object         DirectoryEntry dirEntry = new DirectoryEntry( strConnection );         DirectorySearcher dirSearcher = new DirectorySearcher( dirEntry );         //search for the specific user         dirSearcher.Filter = "(&(objectClass=User)(cn=\"Lonnie Scully\"))";         dirSearcher.SearchScope = SearchScope.Subtree;         SearchResult searchResult = dirSearcher.FindOne();         //retrieve and store the user data         DirectoryEntry dirResult = searchResult.GetDirectoryEntry();         _Firstname = dirResult.Properties["givenname"].Value.ToString();         _Lastname = dirResult.Properties["sn"].Value.ToString();         return;     } } 

Referencing Objects by GUID

Because directory searches can take time, applications should perform only an initial search for an object. Once found, the application should store the unique identifier, or GUID, for that object. If another connection in the future is necessary, it is faster to connect directly to the object based on its GUID rather than perform another search for the same object:

 public string RetrieveNodeGuid() {     String strConnection = "LDAP://srv-enterprise/CN=User";     //establish connection to base object     DirectoryEntry dirEntry = new DirectoryEntry( strConnection );     DirectorySearcher dirSearcher = new DirectorySearcher( dirEntry );     //search for the specific user     dirSearcher.Filter = "(&(objectClass=User)(cn=\"Lonnie Scully\"))";     dirSearcher.SearchScope = SearchScope.Subtree;     SearchResult result = dirSearcher.FindOne();     //return the object's GUID for later binding     return result.GetDirectoryEntry().NativeGuid; } public void ConnectByGuid( string strGuid ) {     //bind to the object by its native guid     DirectoryEntry dirEntry = new DirectoryEntry( strGuid );     //interact with bound object's properties     string strFirstname = dirEntry.Properties["givenname"].Value.ToString();     string strLastname = dirEntry.Properties["sn"].Value.ToString();     return; } 

Using Timeouts

Because the operational status of a directory service is unknown, it can be difficult to determine if a directory service is performing a long search or is simply not available. If a directory service is not available, then using timeouts enables searches to simply time out rather than never returning at all:

 public SearchResult SearchWithTimeout() {     String strConnection = "LDAP://srv-enterprise/CN=User";     //establish connection to base object     DirectoryEntry dirEntry = new DirectoryEntry( strConnection );     DirectorySearcher dirSearcher = new DirectorySearcher( dirEntry );     //set the timeout to one minute     dirSearcher.ClientTimeout = new TimeSpan( 0, 1, 0 );     //set the filter to retrieve the specific user     dirSearcher.Filter = "(&(objectClass=User)(cn=\"Lonnie Scully\"))";     dirSearcher.SearchScope = SearchScope.Subtree;     //execute the search     return dirSearcher.FindOne(); } 



Developing. NET Enterprise Applications
Developing .NET Enterprise Applications
ISBN: 1590590465
EAN: 2147483647
Year: 2005
Pages: 119

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net