Performance: Add index on umbracoContent.contentTypeId - #23328
Conversation
…migration for upgrades.
|
Claude finished @AndyButland's task in 2m 27s —— View job PR ReviewTarget: Adds a non-clustered index on No breaking changes detected. No issues foundThe implementation is clean and correct:
Labels applied: ApprovedThis looks good to be merged as-is, but please do a manual sanity check and testing before merging. |
umbracoContent.contentTypeId
There was a problem hiding this comment.
Pull request overview
Adds a supporting database index on umbracoContent(contentTypeId) to improve performance for content-type-scoped queries (notably published cache rebuild operations triggered by content type structural changes).
Changes:
- Add a DTO-declared non-clustered index on
ContentDto.ContentTypeIdso fresh installs create it automatically. - Add an upgrade migration (
V_17_6_0.AddContentTypeIdIndexForContent) to create the same index on existing databases (guarded byIndexExistsand usingEnsureLongCommandTimeout). - Register the migration step in
UmbracoPlan.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Umbraco.Infrastructure/Persistence/Dtos/ContentDto.cs | Declares the new umbracoContent(contentTypeId) index for schema creation on new installs. |
| src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_6_0/AddContentTypeIdIndexForContent.cs | Adds an upgrade migration to create the index on existing databases using the DTO-defined index definition. |
| src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs | Wires the new migration into the upgrade plan for the 17.6.0 step. |
|
Zeegaan
left a comment
There was a problem hiding this comment.
Makes sense to me 😁
Would love to know how much this improves things 🤔
|
This looks to be an index we clearly should have - it's a foreign key column, used in joins and queries like this one. But I have a request out to test on a large copied customer database that's showing performance issues with this step, so will hopefully have some numbers before merging this in. |



Description
Adds a non-clustered index on
umbracoContent(contentTypeId).The column has a foreign key to
cmsContentTypebut no supporting index. SQL Server does not automatically index foreign key columns, so any query that filters or joins onumbracoContent.contentTypeIdhas to scan the table.That column is on the hot path for content-type-scoped operations — most notably the published cache (
cmsContentNu) rebuild that runs when a document type changes structurally (e.g. a property is removed). That rebuild's delete, row count, and paged node-id selection all filter content by content type via this column:On sites with a large amount of content this scan is a measurable contributor to slow content-type saves (and, in the worst cases, to the SQL command timeouts some customers hit when editing a document type that backs a lot of content). The index lets these queries seek rather than scan.
How it works
ContentDto.ContentTypeId(IX_umbracoContent_contentTypeId), so the schema creator builds it from the DTO like every other index.V_17_6_0.AddContentTypeIdIndexForContent) creates the same index. It uses theCreateIndex<ContentDto>()migration helper, so the index is generated from the exact same DTO definition — the migrated and freshly-installed schemas cannot drift. It is guarded byIndexExists(safe to re-run) and usesEnsureLongCommandTimeoutsince building the index can take a while on large tables.Testing
Solution builds and CI checks should pass. The existing
SchemaValidationTestverifies the DTO-derived schema is internally consistent, which now includes the new index.On starting up Umbraco and running either an attended or an unattended migration, the index should be created: