You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 61e1d57
Browse filesBrowse the repository at this point in the historyBrowse files
perf: fetch table indexes for a schema in one query, not one per table (#88)
## Problem
`enrichColumnsWithKeyAndIndexMetadata` called `getTableIndexes` once per
table inside its loop. On a wide schema that is hundreds of serial round
trips, and it re-runs for every caller that misses the `databaseObjects`
cache.
Measured on a 567-table MySQL connection reached over an SSH tunnel,
`GET /api/connections/{id}/objects`:
| | cache miss | cached |
| --- | --- | --- |
| before | **152.66s / 196.30s** (~270ms per table) | 0.03–0.48s |
| after | **1.09–1.50s** | 0.03–0.48s (unchanged) |
Both pre-fix requests were abandoned by the client (nginx 499). Because
there is no stampede guard, a second caller arriving during the first
sweep starts its own full sweep — so retrying made it worse.
## Fix
Mirrors what `loadForeignKeyColumns` already does one line above: fetch
the whole schema once and group in memory.
Adds `IntrospectionProvider.getAllTableIndexes` with a **default
implementation that loops the existing per-table method**, so a provider
that does not override it is unchanged, plus overrides for both shipped
providers:
- **MySQL** — one `INFORMATION_SCHEMA.STATISTICS` query scoped to a
single `TABLE_SCHEMA`, so it stays bounded on a server hosting many
databases.
- **Postgres** — the same joins and filters as the per-table query, with
`t.relname = ANY(?)` in place of `t.relname = ?`.
## Behaviour preserved
- Tables with no indexes map to an empty list, so callers can
distinguish "no indexes" from "not scanned" without a per-table
fallback.
- A provider returns **no entry** for a name it cannot resolve
precisely, and the caller falls back to the per-table query. Postgres
declines schema-qualified names for that reason; objects qualified with
another database are never offered at all.
- A failed bulk fetch logs and falls back rather than dropping index
flags.
## Verification
- The Postgres form was diffed against the per-table form on a live
database with `EXCEPT ALL` in **both directions**: 744 rows each, zero
rows differing either way.
- Both engines exercised end to end with index flags still populated
(MySQL: 760 columns with a single-column index and 375 composite, of
4588; Postgres: 32 and 2, of 128) and no fallback warnings logged.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments