Skip to main content

Query Engine Deep Dive

This module provides the depth required to work on query engines at companies like PlanetScale, Vitess, CockroachDB, or Supabase. We go beyond EXPLAIN ANALYZE into the actual implementation details. Why this matters for your career: Query engine internals are the single highest-leverage area of database knowledge. Understanding how the lexer, parser, planner, and executor work transforms you from someone who uses a database to someone who can reason about why a query behaves the way it does. At staff+ levels, this knowledge lets you predict plan regressions before they happen, design schemas that cooperate with the planner, and contribute meaningful improvements to the database itself.
Target Audience: Engineers aiming for query engine teams
Prerequisites: Completed Query Processing module
Depth Level: Source code + implementation details
Interview Relevance: Staff+ at database companies

Part 1: Lexer & Parser Internals

1.1 The Lexical Analyzer (scan.l)

PostgreSQL’s lexer is implemented in Flex. Located at src/backend/parser/scan.l.

1.2 Token Categories

1.3 The Parser (gram.y)

PostgreSQL’s parser is a Bison LALR(1) grammar with approximately 15,000 lines — one of the largest Bison grammars in production use anywhere. The grammar defines every legal SQL statement, from simple SELECTs to complex CREATE FUNCTION definitions with procedural bodies. Practical context: The parser is where new SQL features start. When PostgreSQL adds support for a new SQL syntax (like MERGE in PG15), the first patch always touches gram.y to add the new grammar rules. Understanding this file is the gateway to contributing new SQL features.

1.4 Expression Parsing & Precedence

1.5 Parse Tree Node Types


Part 2: Semantic Analysis Deep Dive

2.1 The Analysis Pipeline

2.2 Name Resolution

2.3 Type Coercion System

2.4 Function Resolution


Part 3: Planner Cost Model Internals

3.1 Statistics System

3.2 Selectivity Estimation

3.3 Row Count Estimation

3.4 Cost Calculation Functions

3.5 Cost Parameters Deep Dive


Part 4: Join Algorithms Deep Dive

4.1 Nested Loop Join

4.2 Hash Join

4.3 Merge Join


Part 5: Parallel Query Deep Dive

5.1 Parallel Query Architecture

5.2 Parallel-Safe Operations

5.3 Parallel-Unsafe Functions


Part 6: JIT Compilation Deep Dive

6.1 JIT Architecture

6.2 What Gets JIT Compiled

6.3 JIT Tuning


Part 7: Extended Statistics

7.1 Correlation and Multi-Column Statistics

7.2 Types of Extended Statistics


Part 8: Query Engine Interview Questions

Senior/Staff Level Questions

Answer Framework:
  1. Local vs Distributed Planning
    • Parse and analyze locally
    • Generate distributed plan with data placement awareness
    • Consider network costs in cost model
  2. Data Placement Awareness
    • Track which nodes have which ranges/shards
    • Prefer reading from local replicas
    • Push predicates down to reduce data transfer
  3. Distributed Join Strategies
    • Lookup join: For highly selective joins
    • Hash join: Partition both sides by join key
    • Merge join: If data co-located and sorted
    • Broadcast join: When one side is small
  4. Gateway Routing
    • Plan can be executed partially at gateway
    • Parallel scatter to leaf nodes
    • Gather and merge at gateway
  5. Transaction Considerations
    • Read timestamp selection
    • Write intent placement
    • Conflict resolution
Answer Framework:
  1. Runtime Statistics Collection
    • Track actual row counts at each node
    • Compare with estimates during execution
  2. Trigger Points
    • Cardinality much higher than expected (10x)
    • Memory pressure (hash table exceeds work_mem)
    • Skewed data distribution
  3. Adaptations
    • Switch join algorithm mid-execution
    • Increase parallelism
    • Change join order for remaining tables
    • Switch from hash join to nested loop
  4. Implementation Approach
    • Checkpoint plan execution state
    • Re-plan remaining work
    • Resume with new plan
    • Cache runtime statistics for future queries
Answer Framework:
  1. VSchema (Vitess Schema)
    • Declares sharding key per table
    • Vindexes map column values to keyspace IDs
  2. Query Parsing
    • Parse SQL in VTGate
    • Extract sharding key from WHERE clause
  3. Vindex Lookup
    • Compute keyspace ID from sharding key value
    • Map keyspace ID to target shard(s)
  4. Scatter-Gather for Cross-Shard
    • If query spans shards, send to all
    • Merge results at VTGate
    • Handle ordering, aggregation at VTGate
  5. Optimizations
    • Prepared statement caching
    • Connection pooling per shard
    • Query de-duplication
Answer Framework:
  1. Why Genetic Algorithm
    • Join order optimization is O(n!)
    • For 12+ tables, exhaustive search impractical
    • Genetic algo provides “good enough” in reasonable time
  2. Representation
    • Each chromosome = join order permutation
    • Gene = table position in join sequence
  3. Operators
    • Selection: Tournament selection of fittest
    • Crossover: Edge recombination (preserves edge relationships)
    • Mutation: Random swap of gene positions
  4. Fitness Function
    • Cost of resulting join plan
    • Evaluated using standard cost model
  5. Parameters
    • geqo_threshold (default 12): When to switch from DP
    • geqo_effort (default 5): 1-10, higher = more generations
    • geqo_generations: Number of evolutionary cycles

Part 9: Source Code Exercises

Exercise 1: Trace a Query Through the System

Exercise 2: Add a Custom Operator


Next Steps

Performance Engineering

Profiling, benchmarking, and optimization at scale

Storage Engine Deep Dive

MVCC, vacuum, WAL internals