Typorithm · medium

Indexes, EXPLAIN and measured query reasoning

sqlrelational-datasqlitepostgresqlindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Indexes, EXPLAIN and measured query reasoning

0%

Concept and contract

Inspect an engine's actual plan without treating a tiny fixture as a production benchmark.

An index offers an access path; it does not change the logical result contract. The worked query creates a composite index for country, active status and identity, then requests active Ukrainian identities in order. The accepted result remains 1 and 2, exactly as before the index existed.

The companion lab inspects an engine-specific plan separately. SQLite uses EXPLAIN QUERY PLAN, while PostgreSQL supports EXPLAIN with JSON format. Their output shapes differ, so a test should not compare their textual plans as if they were the same language.

Mechanism and worked example

The equality predicates use leading index columns and the final identity can support the requested order.

The equality predicates use leading index columns and the final identity can support the requested order. That makes the index a plausible candidate, not a guarantee that every engine will choose it on eight rows. PostgreSQL can reasonably prefer a sequential scan for such a tiny table.

Read plan nodes, estimated rows and actual workload context before drawing conclusions. Statistics, distribution, selected columns and competing indexes matter. EXPLAIN without ANALYZE inspects a plan; ANALYZE execution options actually run the statement and therefore need an appropriate bounded test context.

Complete worked example

sql

CREATE INDEX sql_lab_country_active_id ON roles(country,active,id);
SELECT id FROM roles WHERE country='UA' AND active=1 ORDER BY id;
Reasoning
Index creation preserves the two-row logical result.

Counterexamples and common mistakes

The counterexample broadens the country-status contract with OR.

The counterexample broadens the country-status contract with OR. An index cannot make those wrong results correct. Another mistake applies a function to an indexed column and assumes the original index still supports the same search without inspecting a corresponding expression index or plan.

Do not claim a fixed latency improvement from this teaching fixture. Its purpose is result preservation and plan literacy. A production benchmark would need representative cardinality, warm and cold behavior, concurrent load, hardware context and independently recorded timing evidence.

Counterexample: a plausible but wrong query

sql

SELECT id FROM roles WHERE country='UA' OR active=1 ORDER BY id;
Reasoning
A broader predicate remains incorrect regardless of its access path.

Independent practice: small query

Create the same disposable index and query active US identities.

Create the same disposable index and query active US identities. Predict 3 and 4. Inspect the plan using the lab's two engine-specific commands, but do not make the test fail merely because the tiny PostgreSQL fixture chooses a sequential scan.

This task changes the selected value while preserving the access-pattern shape. Compare exact result membership before and after adding the index. The index exists only in each disposable lesson database and is never applied to the production ApplyDjinn database.

Step 1: Create the index only in the disposable lesson database. Step 2: Query active US rows and inspect native plan output.

Practice starter: solve before reading the solution

sql

-- Create the same local index, then select active US role identities.
-- Inspect each engine's native plan separately.
Reasoning
Keep the index shape and change the equality value.
  • Hint 1: Keep country and active equality predicates explicit.
  • Hint 2: Compare exact identities independently of the chosen plan node.

Solution, tests and trade-offs

The solution returns 3 and 4.

The solution returns 3 and 4. The verifier checks that both engines produce their native plan evidence and that result semantics remain correct. It records plan structure without asserting that a particular index node must always be chosen on this small dataset.

If you extend the fixture, populate representative distributions and refresh relevant statistics before comparing plans. More indexes consume space and write maintenance; they are not free universal accelerators. Tie every proposed index to a real predicate, ordering and observed workload.

Practice solution and acceptance checks

sql

CREATE INDEX sql_lab_country_active_id ON roles(country,active,id);
SELECT id FROM roles WHERE country='US' AND active=1 ORDER BY id;
Reasoning
Both engines return 3 and 4; plan evidence does not promise a tiny-fixture index scan.

Interview reasoning and next step

In an interview, connect the query contract to candidate access paths and explain why the optimizer might choose another plan.

In an interview, connect the query contract to candidate access paths and explain why the optimizer might choose another plan. Distinguish an estimate from an observed timing and a full scan from an automatically bad plan. Small-table scans can be entirely reasonable.

The next lesson changes data inside a transaction and verifies both intermediate and final state. Keep those exercises isolated: inspecting and mutating a learning fixture is different from performing maintenance on a running service.

Optional stretch — after the core task works: Generate a larger representative fixture and record plan changes without assuming every full scan is wrong.

Computer practice: https://applydjinn.com/typorithm/sql-lab-20261105.zip. Load the shared setup.sql fixture before running a snippet. The local verifier compares exact ordered row arrays in SQLite and PostgreSQL, keeps SQL values separate from driver bindings and never connects to the production website database.

Inspect an engine's actual plan without treating a tiny fixture as a production benchmark.