Sitemap

Why You Should Stop Using SELECT * in Production SQL

--

If you’ve worked with databases for more than a week, you’ve probably written SELECT * hundreds of times. It’s fast, convenient, and requires zero brainpower when you just want to see what’s inside a table during local testing.

But letting SELECT * slip into your production code is a quiet tech debt trap. It seems harmless on day one, but as your database grows, it actively degrades your app's performance, breaks pipelines, and inflates cloud infrastructure bills.

Here is why you should explicitly name your columns — and why your future self (and team) will thank you.

1. You Waste I/O and Network Bandwidth

When you run SELECT *, the database engine reads every single column off the disk, loads it into memory, and ships it across the network to your application.

If your user table has 25 columns including bio, profile_picture_blob, and json_metadata, but your API endpoint only needs id and email, you are transferring massive amounts of unused bytes over the wire. Multiply this by thousands of concurrent requests, and network latency spikes drastically.

2. You Break Covering Indexes

PostgreSQL and MySQL use indexes to speed up queries. If your query requests only id and email, and you have a composite index on (id, email), the database engine can fulfill the entire query directly from the index tree without touching the underlying table on disk. This is called a covering index scan, and it is ridiculously fast.

Get Abdelkader Ould hennia’s stories in your inbox

Join Medium for free to get updates from this writer.

The moment you write SELECT *, the database is forced to perform a full table lookup on disk to grab the remaining columns, completely throwing away the index benefit.

3. Schema Changes Will Randomly Break Your App

Imagine you have an application layer or an ORM that maps query columns by index or expects a fixed payload shape.

  • Column Addition: Someone adds a heavy last_login_payload JSON column to the table. Suddenly, your lightweight background worker starts consuming double the RAM because SELECT * silently picked up the new column.
  • Column Reordering: If your backend logic maps SQL outputs by position rather than key name, reordering columns in a migration can lead to silent data corruption or runtime type crashes.

Explicitly declaring your columns creates a hard contract between your application and your database schema.

4. It Defeats Memory Caching

App-level caching (like Redis) and database buffer pools rely heavily on memory efficiency. Fetching unneeded blobs or large strings with SELECT * pollutes your cache space with dead weight, forcing out warm data that actually gets hit frequently.

What to Do Instead

Instead of lazy wildcards:

-- Bad: Unpredictable, heavy, bypasses index optimizations
SELECT * FROM users WHERE status = 'active';

Be explicit about what your application actually consumes:

Good: Fast, predictable, minimal payload size
SELECT id, email, first_name FROM users WHERE status = 'active';

SELECT * is great for ad-hoc debugging in your terminal or DBeaver. But in your application codebases, SQL queries should be explicit. Spending five extra seconds typing out column names prevents hours of mysterious production latency debugging down the line.

Press enter or click to view image in full size

--

--

Abdelkader Ould hennia
Abdelkader Ould hennia

Written by Abdelkader Ould hennia

Backend Engineer | Go, Node.js, Laravel, PostgreSQL | High Performance System & Query Optimization | Databases | I am open to Remote, Contract, or Onsite Jobs