1.8 KiB
1.8 KiB
name, description
| name | description |
|---|---|
| db | Design schemas, write migrations, or fix query and data problems. Use when adding a table, writing a migration, debugging a slow query, or choosing keys and indexes. |
Databases
The schema is the hardest thing to change in the whole system. Design it for the queries, not the object model.
Keys and constraints are the real schema
- Every table has a primary key; prefer a surrogate
idunless a natural key is truly stable. - Foreign keys and
NOT NULLare not optional decoration — they are the constraints that stop bad data at the door instead of in application code six months later. - Unique constraints belong on the thing that must be unique (email, slug), enforced by the database, not by a check-then-insert that races.
Migrations are one-way and additive where possible
- Never edit a migration that has run anywhere. Add a new one.
- Destructive changes (drop column, rename, change type) are two migrations: add the new shape, deploy code that writes both, then remove the old in a later release. A single migration that renames a column breaks every old copy of the app still running.
- Test a migration against real data volume.
ALTERon ten rows is instant; on ten million it locks the table.
Indexes follow the queries
Index the columns you filter and join on, in the order the query uses them. A composite index
(a, b) serves WHERE a and WHERE a, b but not WHERE b alone. Read the query plan
(EXPLAIN) before adding one — a guess is an index that costs writes and serves nothing.
The N+1 is the default bug
A query per row in a loop is the most common database performance defect. Fetch the set with a
join or a batched WHERE id IN (...). If a page does one query per item, that is the fix
before any caching.