Index List
The indexes on a table and which are dead weight. An unused index is written on every insert and makes the planner’s job harder — but a primary key with no scans is not flagged, because suggesting you drop one is advice that loses data.
src/components/ui/index-list.tsxAbout
From the component's own source, where it was written.
The indexes on a table, and which of them are dead weight.
An unused index is not free: it is written on every insert, update and delete, it takes space, and it makes the planner's job harder. They accumulate because adding one is easy and nobody ever checks back — so the scan count is the column this component exists to show, and zero is flagged.
A primary key with no scans is *not* flagged. It enforces uniqueness whether or not anything reads through it, and a component that suggests dropping one is giving advice that loses data.
Duplicate indexes — same columns in the same order — are called out separately, because that is the other way this list quietly grows.
Install
npx astralyx-ui add index-list
Usage
import { IndexList } from '@/components/ui/index-list'
<IndexList indexes={indexes} />Composer
Change the props and the source below follows.
Indexes
customers_pkeyprimary(id)
40.1 MB0 scanscustomers_email_keyunique(email)
36.2 MB1,204,918 scanscustomers_created_at_idxnever scanned(created_at)
29.6 MB0 scanscustomers_plan_idxduplicate(plan)
11.4 MB88,412 scanscustomers_plan_dup_idxduplicate(plan)
11.4 MB4 scans
No props to configure.
<IndexList indexes={indexes} />Examples
An unused index and a duplicate
<IndexList indexes={indexes} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
IndexList
The indexes on a table, and which of them are dead weight.
Extends Omit<ComponentProps<'div'>, 'children'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| indexes | DatabaseIndex[] | required | { name, columns, unique?, primary?, size?, scans?, meta? }. Column order matters for a composite index and is preserved. |
| unusedLabel | string | 'never scanned' | — |
| duplicateLabel | string | 'duplicate' | — |
| primaryLabel | string | 'primary' | — |
| uniqueLabel | string | 'unique' | — |
| scansLabel | string | 'scans' | — |
| emptyLabel | string | 'No indexes on this table.' | — |
| format | (bytes: number) => string | formatBytes | — |
| label | string | 'Indexes' | — |
Functions
| Function | Signature | Description |
|---|---|---|
| duplicateIndexes | (indexes: DatabaseIndex[]) => Set<string> | Same columns in the same order. Exported so a migration check can fail on it. |
Types
DatabaseIndex
| Field | Type | Description |
|---|---|---|
| name | string | — |
| columns | string[] | Columns, in index order. Order matters for a composite index. |
| unique? | boolean | — |
| primary? | boolean | — |
| size? | number | Bytes on disk. |
| scans? | number | Dead weight — unless it is the primary key, which earns its keep enforcing uniqueness whether or not anything reads through it. |
| meta? | ReactNode | — |