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.tsx

About

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 scans
  • customers_email_keyunique

    (email)

    36.2 MB1,204,918 scans
  • customers_created_at_idxnever scanned

    (created_at)

    29.6 MB0 scans
  • customers_plan_idxduplicate

    (plan)

    11.4 MB88,412 scans
  • customers_plan_dup_idxduplicate

    (plan)

    11.4 MB4 scans
Props

No props to configure.

tsx
<IndexList indexes={indexes} />

Examples

An unused index and a duplicate

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'>.

PropTypeDefaultDescription
indexesDatabaseIndex[]required{ name, columns, unique?, primary?, size?, scans?, meta? }. Column order matters for a composite index and is preserved.
unusedLabelstring'never scanned'—
duplicateLabelstring'duplicate'—
primaryLabelstring'primary'—
uniqueLabelstring'unique'—
scansLabelstring'scans'—
emptyLabelstring'No indexes on this table.'—
format(bytes: number) => stringformatBytes—
labelstring'Indexes'—

Functions

FunctionSignatureDescription
duplicateIndexes(indexes: DatabaseIndex[]) => Set<string>Same columns in the same order. Exported so a migration check can fail on it.

Types

DatabaseIndex

FieldTypeDescription
namestring—
columnsstring[]Columns, in index order. Order matters for a composite index.
unique?boolean—
primary?boolean—
size?numberBytes on disk.
scans?numberDead weight — unless it is the primary key, which earns its keep enforcing uniqueness whether or not anything reads through it.
meta?ReactNode—