Skip to content

Commit 4e8dd9b

Browse files
authored
perf(postgres-driver): build user defined types map in linear time (#11586)
`loadUserDefinedTypes` built its oid -> typname map with a reduce that spread the accumulator on every row, copying the whole map n times. That is quadratic and fully synchronous, so it blocks the event loop. This went unnoticed while the query only selected `typcategory in ('U', 'E')` (~20 rows on a stock Postgres). #11149 added `'A'` so that array-typed columns get mapped, and Postgres auto-creates an array type for every relation — the row count now scales with the number of tables in the database, not with the number of actual user defined types. Measured on postgres:16, `SELECT count(*) FROM pg_type WHERE typcategory in ('U', 'E', 'A')`: | tables in database | rows | spread reduce | in-place loop | | ------------------ | ---- | ------------- | ------------- | | 0 | 313 | 6.3 ms | 0.12 ms | | 5000 | 5313 | 2355 ms | 0.45 ms | | ~20000 | - | 35116 ms | 1.10 ms |
1 parent d996714 commit 4e8dd9b

1 file changed

Lines changed: 7 additions & 4 deletions

File tree

packages/cubejs-postgres-driver/src/PostgresDriver.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,13 @@ export class PostgresDriver<Config extends PostgresDriverConfiguration = Postgre
315315
[]
316316
);
317317

318-
this.userDefinedTypes = customTypes.rows.reduce(
319-
(prev, current) => ({ [current.oid]: current.typname, ...prev }),
320-
{}
321-
);
318+
const userDefinedTypes: Record<string, string> = {};
319+
320+
for (const row of customTypes.rows) {
321+
userDefinedTypes[row.oid] = row.typname;
322+
}
323+
324+
this.userDefinedTypes = userDefinedTypes;
322325
}
323326
}
324327

0 commit comments

Comments
 (0)