Skip to content

Commit 72f9f80

Browse files
zzstoatzzdomdomegg
andauthored
perf(db): use pk id for lookups and ordering (#390)
summary - use the indexed primary key (`id`) for `getbyid`, `updateserver`, and list ordering/cursor, instead of extracting `_meta...id` from jsonb - in `updateserver`, error if the body tries to change the id; set `meta.official.id` when missing changes - database: `getbyid` → `where id = $1` - database: `updateserver` → `where id = $2`; fail on id mismatch; set id if missing - database: `list` orders by `id` and paginates via `id > $cursor` - no schema or api changes <details> <summary>performance</summary> - env: repo docker compose postgres, 5k–10k rows, warm cache - getbyid: `id` ≈ 0.02 ms vs jsonb path ≈ 0.80 ms - update: `id` ≈ 0.15 ms vs jsonb path ≈ 0.78 ms - list (limit 100): order by `id` ≈ 0.13 ms vs jsonb path id ≈ 2.24 ms (~17x slower) </details> <details> <summary>explain analyze snippets</summary> getbyid by `id` ``` Index Scan using idx_benchmark_servers_id on benchmark_servers (actual time≈0.01–0.02 ms) Buffers: shared hit≈3 ``` getbyid by jsonb path ``` Seq Scan on benchmark_servers (actual time≈0.43–0.83 ms) Filter: ((value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') = $1) Rows Removed by Filter: ≈4999 Buffers: shared hit≈455 ``` update by `id` ``` Update on benchmark_servers … -> Index Scan using idx_benchmark_servers_id … (actual time≈0.007 ms) Execution Time: ≈0.15 ms ``` update by jsonb path ``` Update on benchmark_servers … -> Seq Scan on benchmark_servers … Rows Removed by Filter: ≈4999 Execution Time: ≈0.78 ms ``` </details> <details> <summary>reproduce quickly</summary> - start postgres: `docker compose up -d postgres` - create a simple table (id varchar pk, value jsonb) with several thousand rows - compare plans: `explain (analyze, buffers) select value from … where id = $1` vs the jsonb path predicate </details> --------- Co-authored-by: Adam Jones <[email protected]>
1 parent 7ed56ba commit 72f9f80

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

internal/database/postgres.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ func (db *PostgreSQL) List(
9494
}
9595
}
9696

97-
// Add cursor pagination using registry metadata ID
97+
// Add cursor pagination using primary key ID
9898
if cursor != "" {
9999
if _, err := uuid.Parse(cursor); err != nil {
100100
return nil, "", fmt.Errorf("invalid cursor format: %w", err)
101101
}
102-
whereConditions = append(whereConditions, fmt.Sprintf("(value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') > $%d", argIndex))
102+
whereConditions = append(whereConditions, fmt.Sprintf("id > $%d", argIndex))
103103
args = append(args, cursor)
104104
argIndex++
105105
}
@@ -112,12 +112,12 @@ func (db *PostgreSQL) List(
112112

113113
// Simple query on servers table
114114
query := fmt.Sprintf(`
115-
SELECT value
116-
FROM servers
117-
%s
118-
ORDER BY (value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id')
119-
LIMIT $%d
120-
`, whereClause, argIndex)
115+
SELECT value
116+
FROM servers
117+
%s
118+
ORDER BY id
119+
LIMIT $%d
120+
`, whereClause, argIndex)
121121
args = append(args, limit)
122122

123123
rows, err := db.conn.Query(ctx, query, args...)
@@ -168,7 +168,7 @@ func (db *PostgreSQL) GetByID(ctx context.Context, id string) (*apiv0.ServerJSON
168168
query := `
169169
SELECT value
170170
FROM servers
171-
WHERE (value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') = $1
171+
WHERE id = $1
172172
`
173173

174174
var valueJSON []byte
@@ -230,6 +230,11 @@ func (db *PostgreSQL) UpdateServer(ctx context.Context, id string, server *apiv0
230230
return nil, ctx.Err()
231231
}
232232

233+
// Validate that meta structure exists and ID matches path
234+
if server.Meta == nil || server.Meta.Official == nil || server.Meta.Official.ID != id {
235+
return nil, fmt.Errorf("%w: io.modelcontextprotocol.registry/official.id must match path id (%s)", ErrInvalidInput, id)
236+
}
237+
233238
// Marshal updated server
234239
valueJSON, err := json.Marshal(server)
235240
if err != nil {
@@ -240,7 +245,7 @@ func (db *PostgreSQL) UpdateServer(ctx context.Context, id string, server *apiv0
240245
query := `
241246
UPDATE servers
242247
SET value = $1
243-
WHERE (value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') = $2
248+
WHERE id = $2
244249
`
245250

246251
result, err := db.conn.Exec(ctx, query, valueJSON, id)

0 commit comments

Comments
 (0)