Speeding up directory searches with indexes: the pres, eq, sub, and approx types, olcDbIndex configuration, the attributes that must be indexed, index costs and overhead, and rebuilding indexes with slapindex.

In episode 13 you distributed the directory across many servers. As data grows and consumers serve thousands of binds per second, slow requests become the first complaint. Episode 14 covers the main weapon: indexing — telling slapd which attributes are searched often, so lookups use the index instead of scanning the entire database from start to finish.
Indexes are distinguished by the kind of search they serve. Each attribute can be indexed with one or more types:
| Type | Serves searches | Filter example |
|---|---|---|
pres | Attribute presence | (mail=*) |
eq | Value equality | (uid=budi) |
sub | Substrings | (cn=*bang*) |
approx | Phonetic approximation (soundex) | (cn~=budi) |
| special | Special indexes like entryCSN, entryUUID | internal replication filters |
Substrings can be broken down further into sub:initial, sub:final, and sub:any, but these forms are complex and expensive. The rule of thumb: eq for authentication, sub only when wildcard searches are actually used, and approx is rarely needed.
The special type covers indexes OpenLDAP manages itself for internal needs, not for user filters. entryCSN and entryUUID are in this category: both are used to track entry versions and unique identity, and are very much needed by the syncrepl replication you set up in episode 13. Not all internal attributes need an index — entryCSN eq and entryUUID eq alone are enough for almost all cases.
Indexes are configured per database via the olcDbIndex attribute in cn=config:
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: uid pres,eq,sub
olcDbIndex: cn eq,sub
olcDbIndex: mail pres,eq,sub
olcDbIndex: objectClass eq
olcDbIndex: member,memberOf eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: entryCSN eq
olcDbIndex: entryUUID eqOne olcDbIndex line can hold many attributes at once, like uidNumber,gidNumber eq. entryCSN and entryUUID are the indexes replication leverages in episode 13 — without them, contextCSN and synchronization can slow down. Changes apply immediately, but indexes for existing data are only built during a rebuild.
Indexes aren't for every attribute, but for those frequently used as filters:
objectClass — always; almost every search filters on object class.uid — the most common bind attribute; pres,eq,sub is mandatory.cn — name searches; eq,sub is enough, pres rarely.mail — alternate login and address lookup; pres,eq,sub.member, memberOf — group membership searches from the memberOf overlay.uidNumber, gidNumber — equality searches for POSIX mapping.The simple rule: index every attribute that appears in a filter clause in your applications. An application that frequently filters on (employeeType=contractor), for example, benefits from employeeType eq even if it's not on the list above.
Indexes dramatically speed up searches — a (uid=budi) search without an index scans all 100,000 entries; with an eq index, slapd goes straight to the key in the B-tree. But indexes aren't free:
Index rebuilds are done offline with slapindex, which must run after slapd has stopped:
slaptest -u -v
systemctl stop slapd
sudo -u openldap slapindex -b dc=example,dc=com
systemctl start slapdslaptest -u validates the configuration before the new indexes are used. Run slapindex as the openldap user (not root) so database file ownership stays correct, and make sure slapd is stopped during the rebuild.
Missing indexes aren't always visible at a glance. A few ways to watch for them:
stats logging in olcLogLevel; slow searches that scan the whole dataset are easy to spot from the log pattern.(attr=value) filter without an index forces a full scan; find these by testing the filter directly and timing it.time ldapsearch to measure, and monitor the backend via cn=Monitor to see database activity.time ldapsearch -x -D cn=admin,dc=example,dc=com -W \
-b ou=people,dc=example,dc=com "(cn=*bang*)"How to read the result: if time shows tens of milliseconds, the index is working; if the number jumps to seconds as the database size grows, an index is almost certainly missing or of the wrong type. Compare indexed and unindexed filters on the same dataset to feel the difference concretely.
Tip
Test every new filter in a staging environment before production. A (memberOf=cn=dev,ou=groups,dc=example,dc=com) filter without a memberOf eq index becomes a full scan that drowns the CPU once the member count grows.
One habit that saves you: document the index map in your architecture documents. Write down which attributes are indexed, with which types, and for which application filters. When a new application suddenly gets slow, this map is the first step to guessing whether the needed index already exists — before opening the slapd logs and dissecting slow-running queries.
In this episode 14 you understood OpenLDAP indexing: the difference between pres, eq, sub, and approx indexes, olcDbIndex configuration in cn=config, commonly indexed attributes like objectClass, uid, cn, and mail, the disk and write overhead of indexes, rebuilds with slapindex, and how to monitor index efficiency via logs and time measurements.
Key takeaways:
eq for authentication, sub only when needed — substrings are the most expensive standard index.entryCSN and entryUUID support replication — don't ignore them in multi-server setups.slapindex runs with slapd stopped and as the openldap user.In the next episode, episode 15, we enter the security and encryption phase: LDAP security fundamentals — the types of binds, the risk of plaintext passwords, SASL mechanisms, and the principle of least privilege. The indexes you set up will serve far more secure authentication.