Query Processing and Optimization
From the Advance Database Systems curriculum
Query Processing and Optimization
TL;DR
Query processing is how a database system executes your SQL commands, transforming them into executable steps. Optimization is about finding the most efficient way to run these steps, saving time and resources. It's crucial for getting fast responses from even very large databases.
1. The Mental Model
Think of your SQL query like a recipe. The database system first understands the ingredients and steps you've asked for, then figures out the best way to cook the meal using the available kitchen tools and ingredients, aiming for speed and minimal waste.
2. The Core Material
When you submit a SQL query, it doesn't immediately translate into data being retrieved. Instead, it goes through several stages to ensure it's valid and executed efficiently. This entire process is called query processing. The goal of query optimization is to find the most cost-effective execution plan for a given query.
2.1 Query Processing Stages

Photo by RDNE Stock project on Pexels
-
Parsing and Translation:
- Your SQL query is checked for syntax errors and whether it adheres to the SQL standard.
- It's then translated into an internal representation, often a "parse tree" or "query tree," which is easier for the database to work with. This tree breaks down the query into its fundamental operations (e.g., SELECT, FROM, WHERE, JOIN).
-
Semantic Analysis:
- The database checks if the objects (tables, columns) mentioned in the query actually exist and if you have the necessary permissions to access them.
- It also verifies data types and resolves any ambiguous references.
-
Query Optimization:
- This is the brain of the operation. The optimizer takes the query's internal representation and considers many possible ways to execute it.
- It uses statistical information about the data (e.g., number of rows, distribution of values, presence of indexes) and knowledge about available algorithms (e.g., different join methods, sorting algorithms) to estimate the "cost" of each plan.
- The cost is usually measured in terms of I/O operations (disk reads/writes) and CPU usage, aiming to minimize these.
- The output is an execution plan, which is an ordered sequence of low-level operations.
-
Code Generation and Execution:
- The chosen execution plan is then converted into machine-executable code or a series of calls to database system routines.
- This code is executed, and the results are returned to you.
2.2 Query Optimization Strategies

Photo by cottonbro studio on Pexels
Optimizers primarily use two types of techniques:
-
Heuristic-based (Rule-based) Optimization: These rely on a set of predefined rules that are generally good practices. For example:
- Perform
SELECTandPROJECToperations (filtering rows and selecting columns) as early as possible to reduce the amount of data processed by subsequent steps. - Push down predicates (conditions in the
WHEREclause) to join operations. - Perform inexpensive operations before expensive ones.
- Perform
-
Cost-based Optimization: This is more sophisticated and widely used in modern databases. It involves:
- Collecting Statistics: The database collects data about tables (number of rows, distinct values in columns, histogram of values), indexes (size, depth), etc. These statistics are crucial for accurate cost estimation. You often explicitly tell the database to
ANALYZEorGATHER STATSfor tables. - Cost Model: Each operation (scan, join, sort) has an associated cost formula based on the statistics.
- Search Space Exploration: The optimizer explores various permutations of operations (e.g., which table to join first, which join algorithm to use, whether to use an index). This can be a huge search space, so optimizers often use techniques like dynamic programming or greedy algorithms to find a good, though not always perfect, plan within a reasonable time.
- Collecting Statistics: The database collects data about tables (number of rows, distinct values in columns, histogram of values), indexes (size, depth), etc. These statistics are crucial for accurate cost estimation. You often explicitly tell the database to
Here's a simplified flow of how a query gets optimized:
graph TD
A["SQL Query"] --> B["Parser & Lexer"]
B --> C["Parse Tree / Query Tree"]
C --> D["Semantic Analyzer"]
D --> E["Logical Query Plan (Relational Algebra)"]
E --> F["Cost-Based Optimizer"]
F -- "Considers Statistics & Algorithms" --> G["Physical Query Plan (Execution Plan)"]
G --> H["Executor"]
H --> I["Results"]
2.3 Common Optimization Techniques

Photo by Ann H on Pexels
- Index Usage: Using an appropriate index can drastically speed up
WHEREclause filtering andJOINoperations. - Join Order: The order in which tables are joined can have a huge impact, especially with multiple joins. Joining smaller result sets first is often better.
- Join Algorithms: Databases have different ways to perform joins (e.g., Nested Loop Join, Hash Join, Sort-Merge Join), each suitable for different data sizes and characteristics. The optimizer picks the best one.
- Materialization: Sometimes, storing intermediate results (e.g., from a subquery or a view) temporarily can prevent re-computation and improve performance.
- Predicate Pushdown: Applying
WHEREclauses as early as possible reduces the number of rows that need to be processed by subsequent operations. - Projection Pushdown: Selecting only the necessary columns as early as possible reduces the amount of data transferred and processed.
3. Worked Example
Let's say you have two tables: Customers (CustomerID, Name, City) and Orders (OrderID, CustomerID, OrderDate, Amount). Customers has 1 million rows, Orders has 10 million rows. Both CustomerID columns are indexed.
Consider this query:
SELECT c.Name, o.OrderDate, o.Amount
FROM Customers c
JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE c.City = 'New York' AND o.OrderDate >= '2023-01-01'
ORDER BY o.Amount DESC
LIMIT 10;
A naive execution plan might:
1. Scan all 10 million rows of Orders.
2. Scan all 1 million rows of Customers.
3. Perform a nested loop join (for every order, find its customer).
4. Filter the joined result for City = 'New York' and OrderDate >= '2023-01-01'.
5. Sort the massive filtered result by Amount.
6. Take the top 10.
An optimized plan, leveraging indexes and pushdowns, would likely do something like this:
1. Predicate Pushdown on Customers: Use the index on Customers.CustomerID to quickly find customers where City = 'New York'. This significantly reduces the initial Customers result set (e.g., to 50,000 rows).
2. Predicate Pushdown on Orders: Use an index on Orders.OrderDate (if present) to filter orders where OrderDate >= '2023-01-01'. Or, if no OrderDate index, use the CustomerID index in the next step.
3. Join Strategy: Perform a Hash Join or Sort-Merge Join between the filtered Customers result and Orders (likely using the CustomerID index on Orders for efficient lookups). The optimizer might choose to build a hash table on the smaller Customers filtered set.
4. Projection Pushdown: Only select Name, OrderDate, Amount from the join result, discarding other columns early.
5. Sorting and Limiting: Sort the already filtered and joined result set by Amount and then efficiently retrieve only the top 10, possibly using a "top-N sort" algorithm that doesn't sort the entire result.
The difference in performance between these two approaches can be seconds versus hours on large datasets.
4. Key Takeaways
- Query processing is the full lifecycle from your SQL query to results, with optimization as a critical stage.
- Query optimization aims to minimize execution cost (I/O, CPU) by finding the best execution plan.
- Optimizers use both heuristic rules and cost models based on database statistics to make decisions.
- Key techniques include using indexes, smart join order/algorithms, and pushing down filters (predicates) and column selections (projections).
- Understanding query plans (often viewed with
EXPLAINorEXPLAIN ANALYZE) is crucial for troubleshooting slow queries. - Keeping database statistics up-to-date is vital for the optimizer to make good decisions.
Common Mistakes to Avoid:

Photo by KATRIN BOLOVTSOVA on Pexels
- Ignoring
EXPLAINplans: Never guess why a query is slow; useEXPLAINto see what the optimizer is actually doing. - Missing or outdated statistics: If statistics are old or non-existent, the optimizer will make bad guesses about data distribution.
- Over-indexing: While indexes are good, too many can slow down
INSERT/UPDATE/DELETEoperations. - Using
SELECT *unnecessarily: This fetches more data than needed, increasing I/O and memory usage. - Not understanding join types: Different join algorithms have different performance characteristics depending on data volume and indexes.
5. Now Try It
Choose one of your existing database systems (e.g., PostgreSQL, MySQL, SQL Server) and pick a moderately complex SELECT query that involves at least two joins and a WHERE clause. Run the query with EXPLAIN (or EXPLAIN ANALYZE for more detail) prepended to it. Analyze the output: identify the chosen join type(s), observe if indexes are being used for filtering or joining, and look for any full table scans. Your goal is to understand how the database plans to execute your query based on what you've learned. Success looks like you being able to describe, in your own words, at least three specific operations the database will perform and why they're ordered that way, based on the EXPLAIN output.
Frequently asked about Query Processing and Optimization
More from Advance Database Systems
Get the full Advance Database Systems curriculum
Clone the complete plan to your dashboard for unlimited AI-generated notes, practice quizzes, and a personalised revision schedule.
Create Free Account