Why Fast Code Begins with Constraints, Not Cleverness
Hatched by Kai Nguyen
Jun 04, 2026
9 min read
2 views
82%
The Hidden Similarity Between SQL and Design Principles
What do a slow database query and a messy class hierarchy have in common?
At first glance, almost nothing. One lives in the world of execution plans, indexes, and filters. The other lives in the world of objects, responsibilities, and dependencies. Yet both are fighting the same battle: how to preserve freedom for the machine, or for future developers, by placing smart constraints up front.
That is the deeper question connecting query optimization and software design. We often assume performance comes from adding more power, more logic, more intelligence. But in practice, the best systems are usually the ones that do less work, earlier, and with fewer unnecessary choices.
In SQL, that means being SARGable, filtering early, and letting indexes do what they were built to do. In design, it means applying principles like SOLID so each class stays focused, extensible, and easy to reason about. Both are really about the same discipline: preserving paths for efficiency instead of blocking them with convenience.
Performance Is Usually a Story About What You Prevent
When people hear the word optimization, they imagine speed tricks. They picture special syntax, clever hacks, or extra machinery. But the most important optimization is often subtraction, not addition.
A query becomes faster when it avoids forcing the database to inspect more rows than necessary. That is why a condition like WHERE created_at >= '2025-01-01' can be efficient, while WHERE YEAR(created_at) = 2025 often cannot. The first expression preserves the index’s structure. The second wraps the indexed column in a function, turning a straightforward lookup into a more expensive search.
The same pattern appears in design. A class becomes easier to maintain when it does not try to do everything. A component with one responsibility is easier to extend because changes stay local. A system that respects the Single Responsibility Principle avoids the hidden cost of mixing unrelated logic, just as a query avoids the hidden cost of wrapping an indexed column in arithmetic or negation.
The fastest path is not always the most direct one in code, but it is often the one that keeps the system’s existing structure usable.
This is the important mental shift. Optimization is not about making the computer work harder. It is about removing the obstacles that prevent it from using the structure you already gave it.
Think of a library. If books are arranged by genre, a librarian can find what you need quickly if you ask for a genre directly. But if you ask, “Find all books where genre plus one equals two,” the librarian has to stop using the shelving system and inspect each book manually. That is what happens when you break sargability. And in code design, something similar happens when you bury responsibilities inside tangled classes: the architecture can no longer guide the work, so every change becomes a manual search.
SARGability and SOLID Share the Same Philosophy: Make the Happy Path Easy
The term SARGable sounds technical, but its essence is simple: write conditions that the database can reason about efficiently. That usually means using indexes in ways that preserve their order, avoiding leading wildcards, avoiding unnecessary calculations in the filter, and limiting the result set as early as possible.
SOLID principles operate on a different layer, but the philosophy is strikingly similar. They encourage code that makes the common, correct path easy to follow and the harmful path harder to fall into. A class with a single responsibility is easier to test because it has a narrow job. An interface that is small and specific is easier to implement because it does not demand unrelated behavior. Dependency inversion reduces coupling so that changes do not ripple everywhere.
In both cases, the design question is not just, “Can this work?” It is, “Can this continue working when the system grows?”
That is why these ideas feel abstract at first but become deeply practical once systems scale. A small codebase can survive many inefficiencies. A small table can survive a poorly written query. But scale changes the game. The cost of ignoring structure compounds quietly until it becomes the system’s dominant expense.
Consider a user search feature. A naive approach might store names and then query with WHERE LOWER(name) LIKE '%ann%'. It seems friendly, even flexible. But the leading wildcard prevents the index from helping, and the lowercasing may further block optimization. The database now has to inspect many rows. In design terms, this is like giving every class a vague, overloaded interface just because it seems convenient at first. The result is flexibility that feels immediate but becomes expensive later.
A better approach is often to shape the system around its natural strengths. In the search case, that may mean storing normalized values, adding a dedicated search index, or using a structure designed for prefix matching. In object design, it may mean separating query logic from business logic, or moving special behavior behind small interfaces. In both worlds, the right abstraction is the one that keeps options open for the runtime, not the one that merely compresses work into a single line.
The Real Tradeoff Is Not Simplicity Versus Power, but Locality Versus Entropy
It is tempting to think the choice is between elegant code and performant code. That is false. The real tradeoff is between locality and entropy.
Locality means the system can answer a question using information that is already organized for that purpose. An index gives the database locality. A well designed class gives the programmer locality. The system knows where to look, and it does not need to scan everything.
Entropy is what happens when you destroy that locality. Arithmetic on indexed columns, negations, leading wildcards, unnecessary sorting, and late filtering all increase entropy in a query. In a design, violating responsibility boundaries, coupling unrelated modules, or forcing one class to know too much creates the same problem. The code still works, but now every question is harder to answer.
This is why both SQL and SOLID reward restraint. Restraint is not weakness. It is architectural discipline.
Imagine a restaurant kitchen. If ingredients are stored sensibly, a cook can assemble a dish quickly. If the pantry is random, every order becomes a scavenger hunt. A query optimizer is the cook. An index is the pantry organization. A class design is the division of labor among the staff. If everyone has one clear job and the ingredients are where they belong, speed emerges naturally.
The deeper lesson is that performance is often a property of boundaries. Boundaries tell the system what can be assumed, what can be skipped, and what can be reused. A good database query respects the boundaries of the index. A good object design respects the boundaries of responsibility. In both, the system gets faster when you stop asking it to rediscover structure you already know.
Good design is not the absence of complexity. It is the careful placement of complexity so that the system can ignore most of it most of the time.
A Practical Framework: Ask What the System Must Forget
One way to unify these ideas is to ask a question that is more useful than “Is this elegant?” or “Is this fast?”
Ask: What does this choice force the system to forget?
If you apply a function to an indexed column, the database forgets the index’s order. If you use a leading wildcard, it forgets the prefix structure. If you sort before filtering, it forgets that many rows would have been irrelevant anyway. These are not just performance issues. They are acts of amnesia imposed on the optimizer.
In design, the same question reveals hidden costs. If one class handles persistence, validation, and orchestration, the system forgets where each concern lives. If a method depends on concrete details everywhere, the system forgets which pieces are replaceable. If an interface is bloated, the system forgets which behaviors are truly related.
This framework is useful because it changes the direction of thought. Instead of asking what a construct can do, ask what information it preserves for future use. A healthy abstraction preserves structure. A bad one destroys it.
Here is a concrete example.
Suppose you are building an order system. A quick implementation might place payment logic, inventory updates, and notification sending inside one large service class. It works, and at first it is readable because everything is in one place. But as the system grows, every change becomes risky. A tweak to email logic might inadvertently affect payment handling. The class has become a place where boundaries disappear.
A SOLID aligned approach would split these concerns. The order service coordinates, payment processing lives behind a focused interface, inventory management is separate, and notification logic is isolated. Now changes stay local. The system does not have to remember everything at once.
The SQL equivalent is equally illuminating. A query that filters orders by date, status, and customer before joining a large table allows the database to reduce the working set early. That is not just faster. It is structurally honest. It tells the engine what matters first.
The best systems, then, are not those that maximize raw capability. They are those that minimize the amount of irrelevant work their structure makes inevitable.
Key Takeaways
-
Optimize by preserving structure, not by forcing cleverness. Queries and classes perform better when you let their natural structure do the work.
-
Filter early, separate concerns early. In SQL, reduce rows before sorting or joining. In design, isolate responsibilities before complexity spreads.
-
Avoid transformations that hide meaning from the system. Functions on indexed columns, leading wildcards, and bloated classes all make important structure harder to use.
-
Think in terms of locality. Good indexes and good abstractions both keep related work close together, which makes systems faster and easier to maintain.
-
Ask what your code forces the system to forget. If a choice erases useful order, boundaries, or responsibility, it is probably costing more than it appears.
Conclusion: The Best Systems Respect the Shape of Their Own Work
There is a seductive myth in programming that better results come from adding intelligence somewhere in the stack. More logic. More abstraction. More special cases. But the deeper truth is almost the opposite.
The most effective systems are those that respect the shape of their own work. Databases are fast when queries cooperate with indexes. Codebases are maintainable when classes cooperate with responsibilities. In both cases, the art is not to dominate the system, but to design in a way that lets its native strengths emerge.
That is why SQL optimization and SOLID principles belong in the same conversation. Both teach the same lesson from different angles: the future belongs to systems that waste less effort understanding what they already know.
The next time a query feels slow or a class feels tangled, do not first ask how to add more power. Ask what structure you are ignoring. The answer may be the difference between a system that merely functions and one that scales with grace.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣