← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Database Indexing

performance PHP 5.0+ Intermediate
debt(d5/e3/b5/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The term's detection_hints list mysql-slow-query-log, laravel-debugbar, pt-query-digest, and clockwork — all specialist tools requiring explicit setup. Missing indexes won't cause compiler or linter errors; you need EXPLAIN analysis or slow query monitoring to identify them.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is 'Run EXPLAIN on every slow query; add a composite index' — typically a single ALTER TABLE ADD INDEX statement per table. However, identifying the right columns and order requires analysis, and on large production tables the migration may need scheduling. Not quite e1 (one-line patch) because diagnosis is part of the fix.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). Database indexing applies across all contexts (web, cli, queue-worker) and affects every query touching the indexed tables. Poor indexing choices compound over time as data grows — a missing index acceptable at 10k rows becomes catastrophic at 1M rows. Every new feature touching those tables must consider index coverage.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception states 'Adding more indexes always improves performance' — a documented gotcha that experienced developers learn. Over-indexing slows writes, and low-cardinality index traps are common surprises. The column order trap in composite indexes is another gotcha most devs eventually discover the hard way.

About DEBT scoring →

Also Known As

DB indexes SQL index index optimisation

TL;DR

Indexes are data structures that allow the database to find rows matching a WHERE clause without scanning the entire table.

Explanation

Without an index, a database must perform a full table scan (O(n)) to find matching rows. B-tree indexes (the default in MySQL/PostgreSQL) enable O(log n) lookups. Index design principles: index columns used in WHERE, JOIN ON, and ORDER BY clauses; use composite indexes for multi-column filters; avoid indexing low-cardinality columns (boolean, gender); cover frequently-read queries with covering indexes. Indexes have write overhead — over-indexing slows inserts and updates. Use EXPLAIN / EXPLAIN ANALYZE to verify index usage.

Diagram

flowchart TD
    QUERY[SELECT * FROM orders<br/>WHERE user_id = 42] --> CHECK{Index on
user_id?}
    CHECK -->|No| SEQ[Sequential Scan<br/>read ALL rows O of n]
    CHECK -->|Yes| IDX[B-Tree Index Lookup<br/>O of log n]
    IDX --> ROWS[Fetch matching rows<br/>directly]
    SEQ --> SLOW[Slow on large tables]
    ROWS --> FAST[Fast regardless of<br/>table size]
style FAST fill:#238636,color:#fff
style SLOW fill:#f85149,color:#fff
style IDX fill:#238636,color:#fff

Common Misconception

Adding more indexes always improves performance. Every index adds write overhead and storage cost. Too many indexes slow INSERT/UPDATE/DELETE operations and can confuse the query planner into choosing a suboptimal execution plan.

Why It Matters

Without indexes, every query scans every row — on a million-row table a missing index turns a 1ms query into a 2-second full scan that blocks other operations.

Common Mistakes

  • Not indexing foreign key columns — JOIN and cascade operations do full table scans without them.
  • Over-indexing write-heavy tables — every INSERT/UPDATE must maintain all indexes, slowing writes.
  • Indexing low-cardinality columns (boolean, status with 3 values) — the optimizer often ignores them.
  • Not using composite indexes in the correct column order — (status, created_at) is different from (created_at, status).

Avoid When

  • Indexing every column — unused indexes slow down writes and waste storage without benefiting reads.
  • Indexing low-cardinality columns (boolean, status with 3 values) — the query planner may ignore the index anyway.
  • Adding indexes during peak traffic — index builds lock tables or consume I/O and can cause outages.
  • Indexing columns that are only used in non-selective WHERE clauses that return most of the table.

When To Use

  • Columns used in WHERE, JOIN ON, ORDER BY, or GROUP BY clauses on large tables.
  • Foreign key columns — without an index, deletes and updates on the parent table require full child table scans.
  • Columns used in high-frequency queries identified by EXPLAIN or slow query log analysis.
  • Composite indexes for queries that filter on multiple columns together — column order matters.

Code Examples

✗ Vulnerable
-- Slow: full table scan on 1M rows:
SELECT * FROM orders WHERE customer_id = 42 ORDER BY created_at DESC;
-- No index on customer_id — scans all rows

-- Fast: composite index serves filter + sort:
CREATE INDEX idx_orders_customer_date ON orders (customer_id, created_at DESC);
✓ Fixed
-- Add index on frequently-filtered foreign key
CREATE INDEX idx_orders_user_id ON orders(user_id);

-- Composite index — order matters: equality first, range last
CREATE INDEX idx_orders_status_created ON orders(status, created_at);

-- Partial index (PostgreSQL) — only index relevant subset
CREATE INDEX idx_orders_pending ON orders(created_at)
    WHERE status = 'pending';

-- EXPLAIN confirms index is used
EXPLAIN SELECT * FROM orders WHERE user_id = 42 AND status = 'paid';

Added 15 Mar 2026
Edited 25 Mar 2026
Views 35
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 0 pings S 1 ping S 1 ping M 1 ping T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Perplexity 10 Amazonbot 10 Ahrefs 5 Google 2 Unknown AI 2
crawler 28 crawler_json 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Run EXPLAIN on every slow query; add a composite index on (WHERE cols, ORDER BY cols); avoid indexing low-cardinality columns like booleans
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
EXPLAIN showing type:ALL or rows:>10000; query on unindexed column in WHERE or ORDER BY
Auto-detectable: ✓ Yes mysql-slow-query-log laravel-debugbar pt-query-digest clockwork
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File

✓ schema.org compliant