Skip to main content

What a Partition Is, and Why Pruning Makes a Big Table Cheap

Level 6: Level 6: Cloud & Data Engineering Foundationsmedium26 minpartitioningpartition pruningbytes scannedconditional aggregationcost reduction

Hive-style dt=value folders put the partition key in the path, so a filter on it reads only the matching folders (pruning) and scans a fraction of the bytes, which on a pay-per-scan engine is directly cheaper.

What a partition actually is

Partitioning splits one logical table into many folders, one per value of a partition key, and puts each folder's rows in its own files. The classic key is a date. On a lake the layout is literally directories named key=value:

s3://lake/events/
  dt=2026-01-01/   part-0.parquet  part-1.parquet
  dt=2026-01-02/   part-0.parquet  part-1.parquet
  dt=2026-01-03/   part-0.parquet  part-1.parquet  part-2.parquet

The partition value lives in the path, not inside every row. A query engine reads the folder names from the catalog, so it knows which folders hold which dates before it opens a single file.

Partition pruning: the whole point

When a query filters on the partition key, the engine reads only the matching folders and skips the rest. This is partition pruning. A WHERE dt = '2026-01-03' over a year of daily partitions opens 1 folder out of 365 and ignores the other 364. Because serverless engines charge by bytes scanned (Amazon Athena bills about 5 dollars per terabyte scanned), reading one partition instead of the whole table is not just faster, it is directly cheaper.

Table
A filter on the partition key reads only the matching folder. The engine skips the rest without opening them.
partitionsizeWHERE dt = '2026-01-03'
dt=2026-01-01520 MBskip
dt=2026-01-02540 MBskip
dt=2026-01-03610 MBread
dt=2026-01-04500 MBskip
A filter on the partition key reads only the matching folder. The engine skips the rest without opening them.

Why you partition a large table

Four reasons, in order of how often they come up:

  1. Scan less data. Prune to the partitions a query needs and read a fraction of the table. This is the big one.
  2. Match the common filter. Almost every query on an events table filters by date, so partitioning by date makes almost every query cheap.
  3. Manage the lifecycle. Dropping or expiring old data is a whole-folder operation: delete the dt=2025-01-01/ partition, with no row-by-row delete.
  4. Parallelism. Independent partitions are natural units of parallel work.

Measuring pruning with SQL

A partition catalog records, per partition, its size and row count, so you can compute exactly how many bytes a pruning query scans versus a full scan. The exercises query a partition_catalog and compute the savings from filtering to one day and to a date range.

Common mistake: partitioning a table but never filtering on the partition key. Pruning only happens when a query filters on the key, so a partition scheme your queries ignore adds file overhead with no payoff.

Interview nuance: asked "why would you partition this table," lead with pruning and cost: partitioning by the column you filter on most (usually date) lets the engine skip the partitions a query does not need, so it scans fewer bytes, runs faster, and on a pay-per-scan engine costs less.

On a real platform this differs. A real engine prunes by reading partition metadata from the catalog (Glue) and never lists the skipped folders. The partition_catalog here exposes one row per partition so you can compute the pruned scan yourself; the arithmetic (sum the matching partitions, compare to the total) is what the engine's cost estimate does.

Sample data for this example
CREATE TABLE partition_catalog (
  dt         TEXT,      -- the partition key value, folder dt=YYYY-MM-DD
  file_count INTEGER,
  size_bytes INTEGER,
  row_count  INTEGER
);
INSERT INTO partition_catalog (dt, file_count, size_bytes, row_count) VALUES
  ('2026-01-01', 4, 520000000, 5200000),
  ('2026-01-02', 4, 540000000, 5400000),
  ('2026-01-03', 5, 610000000, 6100000),
  ('2026-01-04', 4, 500000000, 5000000),
  ('2026-01-05', 6, 700000000, 7000000),
  ('2026-01-06', 4, 480000000, 4800000),
  ('2026-01-07', 5, 590000000, 5900000);
Worked example (SQL)
-- For WHERE dt = '2026-01-03', which partitions does the engine scan vs prune?
SELECT dt, file_count,
       ROUND(size_bytes / 1000000.0, 0) AS size_mb,
       CASE WHEN dt = '2026-01-03' THEN 'scan' ELSE 'prune' END AS single_day_query
FROM partition_catalog
ORDER BY dt;

Apply

Your turn

The task this lesson builds to.

Write a query that returns the bytes a single-day query scans versus a full scan, and the percentage of bytes saved, as (partition_bytes, full_scan_bytes, pct_saved), for dt = '2026-01-03' over partition_catalog(dt, file_count, size_bytes, row_count).

partition_bytes is the size of just that day's partition; full_scan_bytes is the whole table. Round pct_saved to 2 decimals.

3 hints and 1 automated check are waiting in the workspace.

Practice

Make it stick

A second problem on the same idea, plus 4 bonus drills.

Write a query that returns how many partitions and bytes a WHERE dt BETWEEN '2026-01-02' AND '2026-01-04' query scans, and the percentage of the table it skips, as (partitions_scanned, bytes_scanned, pct_skipped), over the same partition_catalog table.

Count and sum only the partitions in the date range, and compare their bytes to the whole table. Round pct_skipped to 2 decimals.

3 hints and 1 automated check are waiting in the workspace.