Przejdź do głównej zawartości

Wzorce rozwoju baz danych

Zapytanie raportowe, które na staging skanowało kilka tysięcy wierszy, teraz sekwencyjnie skanuje 40 milionów na produkcji i wykłada dashboard timeoutem. „Szybka” zmiana nazwy kolumny wypuszcza migrację, która zakłada blokadę ACCESS EXCLUSIVE i zamraża każdy zapis na dziewięćdziesiąt sekund. A relacja ORM dodana w zeszłym tygodniu po cichu odpala jedno zapytanie na wiersz, więc strona zamówień wykonuje 500 rund w obie strony, by się wyrenderować. To awarie baz danych, które nie ujawniają się, dopóki nie pojawią się prawdziwe dane i prawdziwa współbieżność — i to tu agent kodujący jest naprawdę użyteczny, bo poprawka to rozpoznawalny wzorzec, a nie wynalazek.

Ten przepis pokazuje prompty, które skłaniają AI do odczytania faktycznego planu EXPLAIN ANALYZE, zaproponowania bezpiecznej migracji expand/contract i zwinięcia N+1 w jedno zapytanie wsadowe. Bazowy stack to PostgreSQL z Drizzle ORM, ale prompty sprawdzają się równie dobrze z Prismą lub czystym SQL-em.

  • Prompt, który wkleja prawdziwy plan EXPLAIN (ANALYZE, BUFFERS) i dostaje z powrotem ukierunkowane rekomendacje indeksów, a nie ogólnikowe porady.
  • Prompt do zmiany nazwy kolumny bez przestoju wykorzystujący wzorzec expand/contract, dzięki czemu zapisy nigdy się nie blokują.
  • Prompt, który zamienia wzorzec dostępu N+1 w ORM w jedno zapytanie wsadowe.
  • Trójnarzędziowy workflow pracy ze schematem (Cursor, Claude Code, Codex) i jak zmienia go serwer MCP dla Postgresa.
  • Listę kontrolną „Gdy to się psuje” dla złych porad, jakich modele AI udzielają przy pracy z bazą danych.

Generowanie schematu to jedno zadanie, w którym wszystkie trzy narzędzia robią z grubsza to samo — czytają Twoje istniejące tabele, dopasowują konwencje, proponują nowe. Różnica leży w powierzchni, z której to napędzasz.

Otwórz swój istniejący plik schematu (src/db/schema.ts), aby tryb Agent miał go w kontekście, następnie Cmd/Ctrl + I:

Zgodnie z konwencjami Drizzle w @src/db/schema.ts, dodaj tabele orders i order_items. Uwzględnij created_at/updated_at z domyślnymi wartościami, deleted_at dla soft delete, klucz obcy z order_items do orders z ON DELETE CASCADE oraz indeks na orders(user_id, created_at DESC) dla naszego najczęstszego wyszukiwania.

Przejrzyj diff przed zaakceptowaniem i użyj Checkpointu, abyś mógł cofnąć całą zmianę schematu, jeśli wybór indeksu jest błędny.

Optymalizacja wolnego zapytania na podstawie jego prawdziwego planu

Dział zatytułowany „Optymalizacja wolnego zapytania na podstawie jego prawdziwego planu”

Największym ulepszeniem strojenia zapytań przez AI jest odmowa pozwolenia mu na zgadywanie. Model, któremu podasz sam SQL, dopasuje wzorzec („dodaj indeks na kolumnach WHERE”) i często się myli. Model, któremu podasz faktyczny plan wykonania, widzi skanowanie sekwencyjne, błąd w szacowaniu liczby wierszy i sortowanie zrzucane na dysk — i rekomenduje indeks, który pasuje.

Dyscyplina, która czyni to niezawodnym: poproś jawnie o CREATE INDEX CONCURRENTLY (zwykły CREATE INDEX blokuje zapisy na dużej tabeli) i wymagaj uzasadnienia względem planu. Jeśli AI rekomenduje cztery indeksy „dla bezpieczeństwa”, sprzeciw się — każdy indeks to podatek od czasu zapisu, a model nie ma pojęcia o Twoim wolumenie zapisów, dopóki mu nie powiesz.

Zmiana nazwy kolumny przez ALTER TABLE ... RENAME COLUMN wygląda niewinnie i jest w porządku na małych tabelach, ale na gorącej tabeli blokada plus przebudowa zależnych widoków może zatrzymać produkcję. Bezpiecznym wzorcem jest expand/contract: dodaj nową kolumnę, uzupełnij dane (backfill), pisz podwójnie z aplikacji, przełącz odczyty, a następnie usuń starą kolumnę w późniejszym wdrożeniu. AI zna ten wzorzec — Twoim zadaniem jest sprawić, by wyprodukowało wszystkie kroki, a nie samą zmianę nazwy.

Wypatruj modelu zwijającego to w pojedynczy RENAME „bo to prostsze”. Jest prostsze — i to właśnie ta rzecz, która wyrwie Cię z łóżka o drugiej w nocy. Backfill wsadowy to część najczęściej brakująca — bez niego jeden wielki UPDATE przepisuje każdy wiersz pod blokadą i właśnie przywróciłeś przestój, którego unikałeś.

ORM-y sprawiają, że N+1 pisze się bezwysiłkowo: iterujesz po liście, dotykasz relacji i już odpaliłeś jedno zapytanie na element. Rozwiązaniem jest załadowanie potomków jednym zapytaniem kluczowanym po ID rodzica. Daj AI kod sprawcy i model, a przekształci wzorzec dostępu.

Krok weryfikacji — „pokaż dwa zapytania SQL” — ma znaczenie, bo niektóre przepisania AI zamieniają N+1 na pojedyncze zapytanie ze złączeniem kartezjańskim, które przesyła te same dane wiersza N razy przez sieć. Dwa czyste zapytania zgrupowane w pamięci to kształt, jakiego chcesz.

  • Wzorce API — idempotentne endpointy, paginacja kursorem i generowanie OpenAPI na bazie tego schematu.
  • Wzorce serverless do uruchamiania tych baz danych w środowiskach chmurowych i edge.