Axiv TechAxiv Tech
  • Home
  • Artificial Intelligence
  • Cybersecurity
  • Data Analytics
  • Web Solutions
  • Updates
Notification Show More
Font ResizerAa
Font ResizerAa
Axiv TechAxiv Tech
  • Home
  • Artificial Intelligence
  • Cybersecurity
  • Data Analytics
  • Web Solutions
  • Updates
  • Home
  • Artificial Intelligence
  • Cybersecurity
  • Data Analytics
  • Web Solutions
  • Updates
Follow US
© 2026 Axiv Tech. All Rights Reserved
Home » Blog » Why SQL Queries Fail at Scale
Data Analytics

Why SQL Queries Fail at Scale

Last updated: April 30, 2026 10:05 am
By Samuel Ogori
Share
7 Min Read
Why SQL Queries Fail at Scale
SHARE

Why SQL Queries Fail at Scale

Contents
It Usually Starts With a Plan That Looked Fine BeforeIndexes Don’t Help If They Don’t Match RealityLoad Changes How Queries BehaveGrowth Breaks Assumptions, Not Just PerformanceWhat Keeps Things Stable Over Time

SQL query performance issues rarely announce themselves early. They sit quietly while your dataset is small, your traffic is predictable, and your indexes happen to align with your queries. Then one day, something shifts (data size, access patterns, concurrency) and the same query that felt harmless starts dragging everything else with it.

This is how most real systems hit their first serious performance wall. One query. No code change. Suddenly it’s responsible for half your database load.

It Usually Starts With a Plan That Looked Fine Before

In one system I worked on, we had a query joining a users table (3 million rows) with an activity table (80 million rows). The query filtered by a recent timestamp and a user status flag. On paper, it was selective enough to use an index. For months, it did exactly that.

Then performance dropped. Not gradually, noticeably. Latency jumped from 120ms to over 3 seconds during peak hours. The query hadn’t changed. The plan had.

The optimizer started choosing a sequential scan on the activity table. Its estimate suggested a large portion of rows would match the filter, so scanning became “cheaper” than using the index. The estimate was off by a wide margin.

Instead of scanning a few hundred thousand rows, it read tens of millions. You could see it clearly once we ran EXPLAIN ANALYZE actual row counts were nowhere near the planner’s expectations.

The root issue wasn’t the query. It was stale statistics combined with a change in how recent activity was distributed across users.

Once we updated stats and adjusted the index to better reflect the filter pattern, the plan flipped back. Latency dropped to 150ms. Same SQL. Completely different cost.

Indexes Don’t Help If They Don’t Match Reality

Another case was more subtle. A payments service had an index on (status, created_at). Most queries filtered by status first, then time. That worked well for a long time.

Then reporting queries started filtering heavily on created_at ranges, with status as a secondary condition. The index was still there. It just wasn’t useful anymore.

Instead of efficient index scans, the database was scanning large portions of the table, then filtering. On a table with 120 million rows, that became expensive fast.

This is one of those problems that looks obvious in hindsight. Index order matters. The database can’t rearrange it for you. MySQL’s documentation on how indexes are structured makes that clear, but it’s easy to overlook when queries evolve over time.

We introduced a new index aligned with the actual query pattern. Not more indexes, just the right one.

Query time dropped from 2.4 seconds to under 200ms. No schema redesign. No caching layer. Just alignment.

Load Changes How Queries Behave

Some problems don’t show up until concurrency increases.

A reporting query in one system ran every few seconds, scanning a moderately large dataset and aggregating results. On its own, it was fine, around 400ms. Under load, it became a problem.

It held locks long enough to block updates on the same table. Not for long, but long enough that with enough concurrent requests, those delays stacked up.

Write latency increased. Then retries increased. Then overall load increased.

That’s how a “read-only” query starts affecting writes.

The behavior lines up with how PostgreSQL describes locking and blocking, but seeing it in production feels different. You don’t just get slower queries—you get cascading effects.

We ended up isolating the workload and adjusting how often the query ran. Not a complicated fix, but not something you’d catch by looking at the query in isolation.

Growth Breaks Assumptions, Not Just Performance

There’s a point where data stops fitting comfortably in memory. You don’t always notice when you cross it, but the database does.

One analytics table grew from ~15GB to ~90GB over a few months. Queries that relied on scanning recent partitions started pulling in more data than expected because “recent” had expanded.

At 15GB, most of the working set stayed in memory. At 90GB, it didn’t.

Disk reads increased. Latency followed. Not dramatically at first, but enough to show up in p95 and p99 metrics.

Joins became heavier too. Intermediate results grew larger before filters were applied, which increased memory usage and occasionally forced temporary data to spill to disk.

That’s the kind of shift you don’t see in code review. It shows up in metrics.

What Keeps Things Stable Over Time

The systems that hold up under growth tend to do a few things consistently.

They look at execution plans early, not just when something breaks. They keep statistics up to date so the optimizer has a realistic picture of the data. They revisit indexes as query patterns evolve, instead of treating them as permanent.

They also watch what actually runs in production. Tools like pg_stat_statements help surface queries that don’t look expensive individually but become costly through repetition. And they accept that performance is not static.

A query that works today can become a liability later without any change in code. The only reliable way to stay ahead of that is to keep checking how the database is executing the work, not just what the SQL says.

TAGGED:SQL

Sign Up For Our Newsletter

Get the latest breaking news delivered straight to your inbox.
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Whatsapp Whatsapp LinkedIn Copy Link Print
BySamuel Ogori
Samuel Ogori is a full stack web developer, and expert in AI application. Skillful in programming languages like NodeJS, React, SQL, JavaScript and other modern frame works. A graduate of Dr. Angela Yu, London App brewery web development boot camp and a certified WordPress developer from Udemy.
Subscribe
Notify of
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Trending Articles

Designing Star vs Snowflake Schemas for High-Growth Data Systems

Choosing between a star schema vs snowflake schema is one of the…

Website Accessibility Standards for Compliance

It’s funny how a single conversation can change your entire perspective. Early…

10 Fixable Code Patterns with Testable Examples

Did you know the most damaging flaws often come from small mistakes,…

Authority Signals in 2025: What Search Engines Reward

When I first started building websites, I tuned headlines, inserted keywords, and…

You Might Also Like

Window Functions in Production: Beyond Ranking and Aggregation
Data Analytics

Window Functions in Production: Beyond Ranking and Aggregation

By Samuel Ogori
How to Debug Slow Queries in Distributed Data Warehouses
Data Analytics

How to Debug Slow Queries in Distributed Data Warehouses

By Daniel Chinonso John
Facebook Twitter Youtube Instagram
Company
  • About Us
  • Contact Us
More Info
  • Privacy Policy
  • Terms of Use

Sign Up For Our Newsletter

Subscribe to our newsletter and be the first to receive our latest updates

© 2026 Axiv Tech. All Rights Reserved
Axiv Tech
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
View preferences
  • {title}
  • {title}
  • {title}
wpDiscuz
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?