From 72f9f80d680f2e88309f4025106d5f44124b359f Mon Sep 17 00:00:00 2001 From: nate nowack Date: Tue, 9 Sep 2025 10:10:55 -0500 Subject: [PATCH] perf(db): use pk id for lookups and ordering (#390) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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
performance - 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)
explain analyze snippets 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 ```
reproduce quickly - 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
--------- Co-authored-by: Adam Jones --- internal/database/postgres.go | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/internal/database/postgres.go b/internal/database/postgres.go index 4a5c26b..3d9d8cf 100644 --- a/internal/database/postgres.go +++ b/internal/database/postgres.go @@ -94,12 +94,12 @@ func (db *PostgreSQL) List( } } - // Add cursor pagination using registry metadata ID + // Add cursor pagination using primary key ID if cursor != "" { if _, err := uuid.Parse(cursor); err != nil { return nil, "", fmt.Errorf("invalid cursor format: %w", err) } - whereConditions = append(whereConditions, fmt.Sprintf("(value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') > $%d", argIndex)) + whereConditions = append(whereConditions, fmt.Sprintf("id > $%d", argIndex)) args = append(args, cursor) argIndex++ } @@ -112,12 +112,12 @@ func (db *PostgreSQL) List( // Simple query on servers table query := fmt.Sprintf(` - SELECT value - FROM servers - %s - ORDER BY (value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') - LIMIT $%d - `, whereClause, argIndex) + SELECT value + FROM servers + %s + ORDER BY id + LIMIT $%d + `, whereClause, argIndex) args = append(args, limit) rows, err := db.conn.Query(ctx, query, args...) @@ -168,7 +168,7 @@ func (db *PostgreSQL) GetByID(ctx context.Context, id string) (*apiv0.ServerJSON query := ` SELECT value FROM servers - WHERE (value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') = $1 + WHERE id = $1 ` var valueJSON []byte @@ -230,6 +230,11 @@ func (db *PostgreSQL) UpdateServer(ctx context.Context, id string, server *apiv0 return nil, ctx.Err() } + // Validate that meta structure exists and ID matches path + if server.Meta == nil || server.Meta.Official == nil || server.Meta.Official.ID != id { + return nil, fmt.Errorf("%w: io.modelcontextprotocol.registry/official.id must match path id (%s)", ErrInvalidInput, id) + } + // Marshal updated server valueJSON, err := json.Marshal(server) if err != nil { @@ -240,7 +245,7 @@ func (db *PostgreSQL) UpdateServer(ctx context.Context, id string, server *apiv0 query := ` UPDATE servers SET value = $1 - WHERE (value->'_meta'->'io.modelcontextprotocol.registry/official'->>'id') = $2 + WHERE id = $2 ` result, err := db.conn.Exec(ctx, query, valueJSON, id)