Slow POST /metadata: ViewEntity query with 6 LEFT JOINs takes 1.6s on cache miss

https://sonarly.com/issue/3775?type=bug

The `FindAllCoreViews` query generates a single SQL statement with 6 LEFT JOINs across 5 independent one-to-many relationships, creating a cartesian product explosion that takes 1618ms. Caching masks the issue for most requests, but cache misses cause ~2s page loads.

Fix: The `findByWorkspaceId` method in `view.service.ts` loaded 6 relations via TypeORM's default `join` strategy, which generates a **single SQL statement with 6 LEFT JOINs**. When 5 of those are independent one-to-many relationships (viewFields, viewFilters, viewSorts, viewGroups, viewFilterGroups), the result set explodes combinatorially — a view with 20 fields × 5 filters × 3 sorts × 5 groups × 2 filter groups yields 3,000 rows for a single view.

Two changes were made:

**1. Add `relationLoadStrategy: 'query'`** — instructs TypeORM to issue one `SELECT … WHERE viewId IN (…)` per relation instead of a single monolithic JOIN query. This avoids the cartesian product entirely. Available since TypeORM 0.3.12; the project uses 0.3.20.

**2. Remove the `'workspace'` relation** — the `workspace` ManyToOne (inherited from `WorkspaceRelatedEntity`) adds 30+ workspace columns to every row of the result set. It is not needed: `ViewDTO` only exposes `workspaceId` (a scalar column already on the view row), and no call site downstream uses `view.workspace`.

```typescript file=packages/twenty-server/src/engine/metadata-modules/view/services/view.service.ts lines=380-395
const views = await this.viewRepository.find({
  where: {
    workspaceId,
    deletedAt: IsNull(),
    ...(viewTypes && viewTypes.length > 0 && { type: In(viewTypes) }),
  },
  order: { position: 'ASC' },
  relations: [
    'viewFields',
    'viewFilters',
    'viewSorts',
    'viewGroups',
    'viewFilterGroups',
  ],
  relationLoadStrategy: 'query',
});
```

After the fix TypeORM will issue 6 lean, targeted queries (one per relation) rather than one 120-column cartesian-product query, reducing the expected cache-miss latency from ~1600ms to well under 100ms.
This commit is contained in:
Sonarly Claude Code
2026-03-06 07:51:43 +00:00
parent 514d0017ea
commit 726969aa33
2 changed files with 815 additions and 1 deletions
File diff suppressed because one or more lines are too long
@@ -385,13 +385,13 @@ export class ViewService {
},
order: { position: 'ASC' },
relations: [
'workspace',
'viewFields',
'viewFilters',
'viewSorts',
'viewGroups',
'viewFilterGroups',
],
relationLoadStrategy: 'query',
});
return views.filter((view) => {