Why `SELECT *` Is Slow

2026-02-025 min read

Why SELECT * Is Slow

If you’ve ever written SQL, chances are you’ve used SELECT *. It’s quick, convenient, and easy to type. But behind that simplicity lies a hidden performance cost that can make your queries and your entire application slower than necessary.

Let’s dig into why SELECT * can hurt performance and what to do instead.

1. It retrieves all columns, even unused ones

When you use SELECT *, the database returns every column from the table, even if you only need a few.

This increases:

  • The amount of data read from disk or memory
  • The amount of data sent over the network
  • The amount of data processed by your application

Example:

SELECT * FROM users;

Suppose the users table has 30 columns and you only need id and email. The database still reads and transmits all 30, wasting I/O and bandwidth.


2. It prevents the use of covering indexes

A covering index can satisfy a query entirely from the index without reading table rows, but only if you select only the indexed columns.

When you use SELECT *, the optimizer can’t rely on any covering index, so it must read full rows from the table.

Example:

SELECT id, email FROM users WHERE id = 123;

Can be served from an index on (id, email)

Must fetch the full row from the table, even if the index has enough info.


3. It may lead to wider row reads and more page I/O

Tables with many columns or large data types (like TEXT, BLOB, JSON) cause more disk pages to be read.

Even if you only need small columns, SELECT * forces the database to read the large ones too.


4. It can break query plan caching

In some databases (e.g., SQL Server, PostgreSQL), SELECT * can make execution plans less stable because adding or removing columns changes the result set shape.

Explicit column lists are more stable for caching and ORM performance.


5. It can hurt maintainability and clarity

While not a direct performance issue, SELECT * makes it harder to:

  • See what data your query actually uses,
  • Track schema changes safely,
  • Optimize or debug queries later.

Better practice:

Always select only what you need:

SELECT id, name, email FROM users WHERE active = TRUE;

If you truly need all columns (e.g., debugging or exporting data), SELECT * is fine, but not in production queries or performance-critical paths.