Save content with related content performance improvments#35773
Save content with related content performance improvments#35773freddyDOTCMS wants to merge 6 commits into
Conversation
❌ Issue Linking RequiredThis PR could not be linked to an issue. All PRs must be linked to an issue for tracking purposes. How to fix this:Option 1: Add keyword to PR body (Recommended - auto-removes this comment)
Why is this required?Issue linking ensures proper tracking, documentation, and helps maintain project history. It connects your code changes to the problem they solve.--- This comment was automatically generated by the issue linking workflow |
|
Claude finished @freddyDOTCMS's task in 1m 52s —— View job Rollback Safety Analysis
Result: ✅ Safe to Rollback — label Analysis summaryThe PR contains pure Java performance refactors in three files:
No category from
|
Summary
Performance degradation when saving content with large many-to-many relationship graphs (reported in support ticket #36004). Saving a single Promotion or Card content type with hundreds/thousands of related items was generating tens of thousands of JDBC queries per save — up to 10 minutes in production.
Multiple root causes were identified across the content save pipeline, all related to unbounded
getRelatedContent()/getRelatedContentFromIndex()calls that load full hydratedContentletobjects (including per-language DB queries viafilterRelatedContentByLiveAndLanguage()) when only identifiers or counts were needed.Performance measured locally with 1 contentlet related to 20,000 items:
Code Fix Summary
ESContentletAPIImpl.validateRelationships()getRelatedContent()called for every child in MANY_TO_MANYONE_TO_MANYcheckESMappingAPIImpl.dependenciesLeftToReindex()getRelatedContent()loaded full contentlets to get old ES statesearchIndex()returning lightweight identifiers onlyESContentletAPIImpl.relateContent()getRelatedContentFromIndex()loaded all related content just to get a count for tree orderingCOUNT(*)SQL queryESContentletAPIImpl.addRestrictedContentForLimitedUser()getRelatedContentFromIndex()loaded all related content to find restricted itemsESContentletAPIImpl.deleteRelatedContent()DELETEstatements per related itemDELETE WHERE parent=? AND relation_type=?ESContentletAPIImpl.relateContent()insert loopsaveTree()calls (DELETE+INSERT each)TreeFactory.insertTrees()addRestrictedContentForLimitedUser()has been temporarily commented out for testing purposes. A proper fix (likely a short-circuit for admin/system users who can read all content) must be implemented before this PR is ready for merge.Checklist
addRestrictedContentForLimitedUser()before mergeRelated