padosoft-database-designlisted
Install: claude install-skill padosoft/skills
# Database design
An index is not a performance tweak added later — it is part of the table's design, and so is the primary
key, the partition and the decision to put something in a JSON column. Getting them wrong is cheap to fix on
day one and expensive on day four hundred.
---
## 1. Which columns get an index by default
Always, unless there is a reason not to: **boolean and flag columns, dates and datetimes, and descriptive
text columns** (name, title, description) — because those are what the admin side filters, sorts and
searches on, systematically.
Then, without exception: **every column involved in a `JOIN`, `WHERE`, `ORDER BY`, `GROUP BY` or `HAVING`**.
Two exemptions: the column is already the **leftmost prefix** of an existing composite index, or the table
will never hold more than a few thousand rows.
```php
$table->index('active');
$table->index('starts_at');
$table->index(['brand_id', 'active'], 'idx_art_brand_active'); // idx_<table>_<col>_<col>
```
## 2. Designing the index for a query: three stars
| Star | Columns | Not available when |
|---|---|---|
| ★ | the equality predicates of the `WHERE`, joined by `AND` | the `WHERE` uses `OR` or complex expressions |
| ★★ | the `ORDER BY` / `GROUP BY` columns, **in their direction** | grouping and ordering differ |
| ★★★ | the remaining selected columns — a covered index | optional, but it removes the row lookup entirely |
```sql
-- SELECT name, price FROM articles WHERE brand_id = ? AND active = 1 ORDER BY