mastering indexing in servicenow: a complete developer’s guide

Many ServiceNow developers/architects don’t realize it, but poor indexing is one of the reasons for slow performance in ServiceNow. A well-written script or query means nothing if the underlying data retrieval is inefficient.

We Developers/Architects only think about indexing when queries start slowing down—but by then, it’s too late. A lack of indexing means instance struggles under load, searches return irrelevant results, and database queries take forever. Learning how to properly use database and Zing indexes will helps to write optimized queries, improve ServiceNow’s efficiency, and avoid future performance nightmares.

What is Indexing

Indexing is a technique used to optimize database performance by creating a structure ( Usually B-Tree data structure) that allows faster retrieval of data.

Think of it like an index in a book — instead of reading every page to find a topic, we can go directly to the page number listed in the index.

How Indexing Works

Lets understand this by using an example: Assume we have incident table with 5 million records and we enable index for Number field.

The DB engine creates a separate B-Tree structure for the Number field.
Each entry in the B-Tree has:
- Key: The field value (e.g., "INC0012345")
- Pointer: A reference to the actual row in the table

Now when we use query something like below:

    
var grIncident=new GlideRecord("incident");
grIncident.addQuery("number","INC0012345");
grIncident.query();
    
The database follows below steps:
- Looks into the B-Tree index
- Finds the key 'INC0012345'
- Retrieves the pointer to the actual row
- No need to scan 5 million records

Without indexing, every query would trigger a full table scan, slowing down the platform significantly.

Database Indexing vs Zing Indexing in ServiceNow

1. Database Indexing:

Database indexing is used to speed up SQL queries by allowing the system to locate records more efficiently. It is managed at the database level and improves query execution time by avoiding full table scans. Without indexing, searches on large tables become slow and inefficient.

Example: Lets assume that we need to fetch incidents created in the last 7 days using a GlideRecord query, so we write script as below:
        
var gr = new GlideRecord('incident');  
gr.addQuery('sys_created_on', '>=', gs.daysAgoStart(7));  
gr.query();  
while (gr.next()) {  
    gs.info('Incident: ' + gr.number);  
}

Adding an index on the sys_created_on field improves performance by allowing the database to efficiently fetch only the relevant records. If no index exists on the sys_created_on field, ServiceNow has to scan every record in the incident table, leading to poor performance, especially in large instances.

2. Zing Indexing:

A Zing Indexing is designed to enable fast and efficient full-text searches. It powers Global Search, Service Portal Search, and Knowledge Base Search, allowing users to retrieve relevant records quickly by scanning across multiple text fields rather than performing traditional database queries.

Example: To optimize search performance, we can enable Zing indexing on fields such as short_description and description in the Incident table. This ensures that incidents containing specific keywords are easily discoverable in Global Search or the Service Portal.

Example with gliderecord: Let's assume we want to retrieve all incidents that contain the phrase "Outlook Issue" anywhere in record. We can use the following script:

            
//This code returns all incidents where indexed fields contain "Outlook Issue" keyword
var gr = new GlideRecord('incident');  
gr.addQuery('123TEXTQUERY321', 'Outlook Issue');  // Uses Zing full-text search  
gr.query();  

while (gr.next()) {  
    gs.info('Matching Incident: ' + gr.number);  
}
            
        
In the background, this search leverages Zing indexing, enabling faster and more efficient retrieval of relevant records.

Note: The above script demonstrates how to perform a full-text search using Zing indexing by using GlideRecord. However, Zing search is primarily managed by ServiceNow in the backend for Global Search, Service Portal Search, List View Search, and Knowledge Base Search, ensuring optimized and efficient search performance.

How to configure fields for database indexing

Lets perform indexing on incident table on state field to understand steps in details:

1. Open Incident Table Configuration.
2. Scroll down to related list and we can see Database Indexes tab as shown below:

3. Click New button, you will see below popup

4. Select fields where you would like to add index, we can also add multiple fields ( called as composite indexing ).

Types of database Indexing

Primary Index

This indexing is applied on unique identifier for a record, usually on the sys_id column. Every table in ServiceNow has a primary index on the sys_id field.

Unique Index

Ensures that values in a column (or combination of columns) are unique.
Example: A unique index on the user_name column in the sys_user table prevents duplicate usernames.

Composite Index

It is applying index on multiple columns to optimize multi-condition queries.
Example: Indexing assigned_to and state together in the incident table.

Non-Unique Index

Speeds up queries but does not enforce uniqueness. Very useful for frequently queried fields (e.g., category, priority).
Example: Indexing the state column in the incident table to optimize searches by state.

Configuring and Managing Zing Indexing in ServiceNow

As we previously discussed zing indexing is part of the Zing Search Engine used in ServiceNow for full-text searches, including Global Search, Service Portal Search, and Knowledge Base search. So, lets understand how we can configure it in servicenow.

Configure a table for indexing and searching

- Navigate to All > System Definition > Text Index Configurations and select New.
- In Applies to, select Table.
- In Table, select the table that you want to configure text indexing for.

Here is an example for an Incident table:

Configure the fields to be indexed

- Navigate to All > System Definition > Text Index Configurations and select a table.


- In the Text Index Column Attribute Maps related list, select New.
- On the Text Index Column Attribute Map form, fill in the fields.

Here is an OOTB example for short desciption field on Catalog Item table:

Essential Indexing Considerations for ServiceNow Developers

Analyse slow running queries in Instance

Navigate to System Diagnostics > Slow Queries


Look at:
1. Query Execution Time
2. Query Type (SELECT, UPDATE, DELETE)
3. Table Names & WHERE Conditions

Common Red Flags:
1. Full table scans (WHERE without an index)
2. Queries using LIKE %search_text% (bad for indexing)
3. Too many joins (INNER JOIN, LEFT JOIN)

Use Composite Indexes for Multi-Field Searches

If queries involve multiple conditions on different fields, a composite index can improve efficiency
Example:

    
var gr = new GlideRecord('task');
gr.addQuery('assigned_to', 'john.doe');
gr.addQuery('state', '2');  // Work in Progress
gr.query();
    
Instead of separate indexes on assigned_to and state, a single composite index on (assigned_to, state) can speed up retrieval.

Avoid Indexing Frequently Changing Fields

Fields that change frequently (e.g., state, sys_updated_by, sys_updated_on) can cause performance overhead if indexed.
Indexing should be used for fields that are frequently searched but don’t change often.

Exclude Unnecessary Fields from Indexing

Fields like sys_id, sys_updated_on, encrypted fields should not be indexed to reduce search overhead.
We can manage this via field dictionary "no_text_index" attribute.

Be Mindful of Stop Words in Zing Indexing

You may have encountered the following error when searching for specific text in list view or service portal:


This happens because ServiceNow automatically marks frequently occurring keywords as stop words, which are ignored in full-text searches to improve performance.

To override this, navigate to the ts_index_stop table and mark the word as "Not a Stop Word" if needed. However, proceed with caution—re-enabling stop words can impact search efficiency, especially if the word appears excessively across the instance.

Final Thoughts on Indexing in ServiceNow

Even with a well-balanced indexing strategy, the system still incurs additional performance costs to manage indexes efficiently. Here are some key areas where indexing, adds overhead:

Factor System Performance Overhead Due to Indexing
Record Insert/Update/Delete Every indexed field requires additional processing, as the system must update the B-tree structure to maintain the index. This adds overhead, slowing down insert, update, and delete operations since the database needs to reorganize and rebalance the index whenever data changes.
Storage Consumption Indexes take up additional database space because they store a sorted copy of the indexed columns, separate from the main table data. Additionally, B-tree indexes require extra space for storing pointers, metadata, and internal balancing structures. As more fields are indexed, the database needs to maintain multiple index structures, further increasing storage requirements.
Index Maintenance The system periodically rebuilds and updates indexes, consuming CPU and memory resources, especially in large datasets.
Index Rebuild Time During instance upgrades or table structure modifications, indexes must be recalculated, which can extend maintenance windows.

Key Takeaway

The key to effective indexing is balance—index only what is necessary to speed up queries while avoiding excessive indexing that can degrade performance. By carefully analyzing query patterns, data volume, and system performance, developers can ensure optimal indexing strategies that enhance both speed and stability in ServiceNow.

Comments

Siddharth 2025-04-22 06:20:04
Awesome article, Abhijit! I didn't know we could still improve performance with composite keys even if the script’s already optimized. Super helpful tip!