Skip to main content
Version: Next

ServiceNow Table-Per-Hierarchy (TPH) Mirrors

When ServiceNow provides a native database export (as opposed to a schema-for-service export), it may use the table-per-hierarchy (TPH) storage model. This is a different way of organizing data than traditional per-table schemas, and understanding it helps explain how certain forms, fields, and related lists behave in Cortex.


What Is TPH?​

In the TPH model, multiple logical record types share a single physical table. For ServiceNow archives, the most common example is the task table family:

  • incident, change_request, problem, sc_task, rm_release, sn_cust_service_case, and other business objects all inherit from the base task table
  • In a TPH mirror, all of these share one physical task table
  • Each row in task has a sys_class_name field that identifies which logical type it actually is

This means:

  • When Cortex browses Incidents, it queries task filtered to sys_class_name = 'incident'
  • When it browses Change Requests, it queries task filtered to sys_class_name = 'change_request'
  • Multiple logical tables map to the same physical table

Anonymous Storage Columns (a_* Columns)​

Each logical subclass of task has its own set of specialized fields. For example, change_request has:

  • change_type — the type of change (normal, emergency, standard, etc.)
  • risk — the risk level
  • phase — the change lifecycle phase
  • assignment_group — the group assigned (inherited from task but may use a different reference field slot)

In a traditional per-table schema, each subclass would have its own table with named columns for these fields. In a TPH mirror, the physical task table needs somewhere to store these subclass-specific values.

ServiceNow handles this by allocating anonymous storage columns — generic slots named a_ref_1 through a_ref_24 (for reference values), a_str_1 through a_str_100 (for string values), and similar for boolean, integer, and other data types. Each subclass's specialized fields are mapped to specific anonymous slots.

How Cortex Resolves Anonymous Slots​

Cortex resolves which anonymous slot corresponds to which logical field by consulting metadata tables:

  • sys_schema_attribute — maps logical field names to storage slots (e.g., change_type → a_str_15)
  • sys_schema_attribute_m2m — multi-value field mappings
  • sys_storage_alias — aliases for storage table references
  • sys_storage_table_alias — aliases for storage table references at the table level

When this metadata is present in the export (it is included in full database exports), Cortex can read the mappings and properly display subclass-specific fields. When this metadata is missing or empty, those fields are not resolvable and may appear blank.


How the Mirror Builds a TPH Parent Table​

When Cortex builds a native ServiceNow mirror, the physical table for a TPH family is created from the field definitions of the parent table and of every logical table whose rows are stored on it. A subclass-only field such as incident.caller_id — or the a_ref_* slot it uses when the export relies on slot storage — therefore becomes a real column on the mirrored task table. That is what lets reference fields on a subclass record form resolve, using the same column set the browse grid already relies on.

Grandchildren are attributed to the outermost physical table that actually holds their rows. For example, change_task rows live on task (through change_request), so their fields are added to task as well. The sys_metadata table family is handled separately.

If one of those child field definitions cannot be read — the live sys_dictionary query fails, or returns an incomplete page with no preloaded copy to fall back on — Cortex does not build a parent table with silently missing columns. The table is marked Failed in the mirror job with a message naming the child tables it could not fully load, for example:

TPH parent task subclass columns could not be fully loaded for: incident. The scheduler retry loop will re-attempt this table.

Picking Up New Columns on an Existing Mirror​

Re-run the mirror job to pick up columns that a newer Cortex version resolves. The schema step adds any missing columns to the existing physical table as nullable columns and the copy phase populates them, so you do not need to drop and rebuild the mirror.


Impact on Browse, Search, and Forms​

Browse — Table Selection​

Because multiple logical tables share one physical table, Cortex must resolve which physical table corresponds to which logical table when browsing. Cortex first attempts to match by the exact logical sys_id from sys_db_object. If no exact ID match is found, it falls back to matching by physical storage name (task), but this may pick the wrong logical entry if multiple subclasses share the same storage name.

Searching across task-family records searches the physical task table, filtered by the appropriate sys_class_name value based on the selected business object.

Because anonymous slots are not named in the physical mirror, Cortex labels them from mapping metadata so the search field picker stays readable:

  • A slot that is mapped to a logical element - either through the mirror's own schema-attribute metadata or through the manual Attribute Mappings on the ServiceNow data source - is offered under that element's ServiceNow label, for example Change Type rather than a_ref_12.
  • Slots with no mapping are hidden from the search field picker, so you are not handed a long list of unlabeled a_* entries.
  • Only the pickers are filtered. Table definitions elsewhere - the Attribute Mappings editor, the Database Inspector, and record forms - still show every physical slot.
  • To make a slot searchable, add a mapping for it under Attribute Mappings; the mapping is the source of truth and takes precedence over metadata-derived labels.

The physical column is still what gets searched and exported - only the label you see changes.

note

Label resolution depends on the mapping metadata being present in the mirror (sys_schema_attribute / sys_storage_alias, as listed above). If a mirror was exported without that data and no manual mappings exist, slots keep their raw names and stay hidden from the pickers.

Record Forms​

When viewing a record form, Cortex reads the record's sys_class_name to determine which form layout to render. The form layout (from sys_ui_form, sys_ui_form_section, and sys_ui_element) references the logical table, so the form renders the correct fields for that record type — even though all records physically live in task.

Related lists on TPH records can appear empty if the reference field (e.g., rfc, change_request, caused_by) is stored in an anonymous a_ref slot. Cortex checks whether the named column exists on the physical table; since these values live in anonymous slots (not named columns), the system falls back to alternative resolution paths. See Database Inspector & Diagnostics for troubleshooting.


Metadata Tables to Include in Your Export​

For TPH mirrors to work correctly, the following metadata tables must be present in the database:

  • sys_db_object — logical table definitions
  • sys_dictionary — field definitions per logical table
  • sys_schema_attribute — anonymous slot mappings (essential for resolving a_* columns)
  • sys_schema_attribute_m2m — multi-value slot mappings
  • sys_storage_alias — storage table reference aliases
  • sys_storage_table_alias — storage table aliases at the table level

These tables are automatically included when using the Cortex Sync Utility or a full database export. If you are working with a partial or filtered export, verify these tables are present.


Diagnosing TPH Issues​

Cortex includes diagnostic tools to help identify and resolve TPH-related issues:

  • Mirror job table errors — a table marked Failed with a message naming TPH child tables means subclass columns for that parent could not be fully loaded; the job retries the table automatically
  • Database Inspector → Related List Diagnostics — shows which related lists are renderable per table, with reasons when they are not
  • Database Inspector → Attribute Mappings — view and configure slot-to-field mappings
  • Database Inspector → Field Type Mismatch — identify physical data type vs. expected type differences

See Database Inspector & Diagnostics for more information.