Database Partitioning Strategy¶
1. Decision¶
Choose Horizontal Range Partitioning for time-series and sequential data; choose Horizontal Hash Partitioning for uniform write distribution across shards; choose List/Directory Partitioning for explicit tenant or geographic data isolation; choose Vertical Partitioning to separate frequently accessed lean columns from heavy blob columns.
2. 30-Second Answer¶
Database Partitioning divides a large logical dataset into smaller, managed physical subsets (partitions) to improve query performance, manageability, and write throughput. Horizontal Range Partitioning splits rows by value ranges (e.g., created_at by month/year), enabling instant partition pruning for time-series queries but risking write hotspots on current ranges. Horizontal Hash Partitioning applies a hash function (hash(key) mod N) to distribute rows evenly across partitions, eliminating write hotspots but breaking range scan efficiency. List / Directory Partitioning routes rows explicitly based on discrete values (e.g., country_code or tenant_id). Vertical Partitioning splits table columns into separate physical storage files, isolating high-frequency narrow columns from large, infrequently accessed binary/text attributes.
3. Decision Matrix¶
| Option | Best For | Avoid When | Latency | Scalability | Consistency | Operational Complexity |
|---|---|---|---|---|---|---|
| Horizontal Range Partitioning | Time-series data, logs, metrics, financial transaction archives by date range | High-velocity real-time writes where current timestamp creates single-partition write hotspots | Low for range queries inside partition; High if scanning across all range files | Medium (Requires automatic partition creation scripts) | Strong within instance; Range boundary checks | Medium |
| Horizontal Hash Partitioning | Uniform write distribution, user profiles, account ledgers, high-concurrency OLTP | Range queries (WHERE date BETWEEN X AND Y) requiring contiguous scans |
Low for single key lookups; High for range scans across all hash buckets | High (Spreads writes evenly across \(N\) physical storage partitions) | Strong per partition | Medium |
| List / Directory Partitioning | Multi-tenant SaaS isolation, geographic data residency compliance (GDPR) | High-cardinality dynamic attributes without fixed discrete lists | Low for tenant-isolated queries | High (Easily isolate or migrate single tenant partitions) | Strong per partition | Medium |
| Vertical Partitioning | Tables with 50+ columns containing heavy text/blob columns (TEXT, BLOB) alongside lean scalar columns |
Applications fetching all columns (SELECT *) simultaneously on every query |
Low (Reduces disk I/O page reads for hot columns) | Medium (Keeps core index/table lean in memory) | Strong across columns via primary key | Low to Medium |
4. Selection Rules¶
| Requirement | Best Choice | Rationale / Example |
|---|---|---|
| Time-Series / Logging Data (Prometheus / Timescale) | Range Partitioning | Partition by created_at (daily/monthly); drop old partitions instantly via DROP TABLE |
| Eliminate Write Hotspots in High-QPS OLTP | Hash Partitioning | Partition by hash(user_id) to distribute writes evenly across 64 storage buckets |
| Multi-Tenant SaaS Data Residency (GDPR) | List Partitioning | Partition by country_code: EU partition stored on Frankfurt cluster, US in N. Virginia |
Isolate Heavy TEXT/BLOB Columns |
Vertical Partitioning | Split users into user_core (id, email, password) and user_profile (bio, avatar_blob) |
| Instant Purging of Historical Data | Range Partitioning | DROP PARTITION p_2023_01 deletes disk files in milliseconds without DELETE WAL overhead |
5. Tradeoffs¶
- Range Partitioning Pruning vs Single-Partition Write Hotspotting
- Gain (Range): Query planner skips 95% of disk partitions when filtering by date range (
Partition Pruning). - Lose (Range): 100% of current incoming writes hit the latest date partition, bottlenecking single disk I/O.
- Hash Partitioning Uniformity vs Loss of Range Scans
- Gain (Hash): Perfect \(1/N\) write distribution across all storage partitions.
- Lose (Hash): Range queries (
WHERE age BETWEEN 20 AND 30) must scan every hash partition. - Vertical Partitioning I/O Efficiency vs Multi-Table Join Overhead
- Gain (Vertical): Core table disk pages fit 10x more rows in RAM buffer pool, accelerating index scans.
- Lose (Vertical): Queries requesting full entity profiles require joining two physical tables together.
- List Partitioning Isolation vs Unbalanced Tenant Growth
- Gain (List): Isolate enterprise tenants to dedicated physical partitions for security/compliance.
- Lose (List): An enterprise mega-tenant creates a "whale partition" that outgrows others.
- Declarative Database Partitioning vs Application-Level Sharding
- Gain (Declarative): Database engine manages routing transparently within a single DB instance.
- Lose (Declarative): Still bounded by single DB instance CPU/RAM limits (unlike distributed sharding).
6. Interview Counter Questions¶
- How does Partition Pruning work in PostgreSQL / MySQL query planners?
- Why is dropping a range partition (
DROP TABLE partition_name) 1,000x faster than runningDELETE FROM table WHERE date < X? - How do Primary Keys and Unique Constraints interact with partitioned tables in PostgreSQL?
- What is the difference between Single-Level Partitioning and Composite (Sub-partitioning) Partitioning?
- How do you handle write hotspotting when range-partitioning time-series data?
- How does Vertical Partitioning differ from Columnar Storage (ClickHouse/Parquet)?
- What happens if an
INSERTstatement supplies a partition key value that does not match any existing List/Range partition? - How do Global Secondary Indexes vs Local Secondary Indexes work on partitioned tables?
- When would you combine Hash Partitioning with Range Partitioning (Composite Hash-Range)?
- How do you automatically create future date partitions in PostgreSQL (pg_partman extension)?
10. Gold Standard Answers¶
- Partition Pruning: During query optimization, the planner checks
WHEREconditions against partition constraints. IfWHERE created_at >= '2026-01-01', it excludes all pre-2026 partition disk files from the execution plan. DELETEscans every tuple, writes individual row deletions to the Write-Ahead Log (WAL), updates secondary indexes, and requires Autovacuum cleanup.DROP PARTITIONsimply unlinks the physical file from the OS filesystem instantly.- In PostgreSQL, any
PRIMARY KEYorUNIQUEconstraint on a partitioned table must include the partition key column. Otherwise, the database would have to check uniqueness across every single partition file on every insert. - Single-Level uses 1 strategy (e.g., Range by Date). Composite (Sub-partitioning) uses 2 layers (e.g., Range by
dateat top level, then Hash byuser_idinside each date partition) to prevent single-partition size bloat. - Combine Hash + Range partitioning (sub-partitioning), or write incoming real-time time-series data to an in-memory buffer (Redis / Kafka) and batch ingest into historical range partitions.
- Vertical Partitioning manually splits a table into 2+ row-oriented tables joined by Primary Key. Columnar Storage natively stores every individual column in separate compressed files at the storage engine level.
- The database throws an execution error (
no partition found for row). Mitigate by defining aDEFAULTpartition to capture unmatched rows, or using automated background partition creation (pg_partman). - Local Secondary Index: Indexed per partition; query missing partition key forces scatter-gather across all local indexes. Global Secondary Index: Single index spanning all partitions; fast lookup, but complex cross-partition updates.
- Use Composite Hash-Range (e.g., Hash by
user_idto distribute write traffic evenly across 16 nodes, then Range bymonthinside each node for easy historical data purging). - Use
pg_partman(PostgreSQL Partition Manager extension). It runs scheduled background jobs to create future date partitions automatically (e.g. 7 days ahead) and archive/drop expired historical partitions.
8. Common Mistakes¶
- Failing to include the partition key in primary/unique constraints, causing DDL migration errors in PostgreSQL.
- Range-partitioning by date without setting up automated future partition creation (
pg_partman), causing productionINSERTcrashes when a new month begins. - Running
DELETE FROM table WHERE created_at < dateon massive tables instead of usingDROP PARTITION. - Hash-partitioning a time-series table and wondering why date range queries execute full table scans across all hash buckets.
- Over-partitioning a database into thousands of tiny partitions (<10MB each), exhausting OS file descriptors and query planner memory.
9. Keywords¶
Database Partitioning, Horizontal Partitioning, Vertical Partitioning, Range Partitioning, Hash Partitioning, List Partitioning, Partition Pruning, Composite Partitioning, Sub-partitioning, DROP PARTITION, Local Secondary Index, Global Secondary Index, pg_partman, DEFAULT Partition.
10. Cheat Sheet¶
- Range Partitioning: Best for time-series / logs (
created_at). Enables fast Partition Pruning and instantDROP PARTITIONpurging. Risk: Write hotspots on current date. - Hash Partitioning: Best for uniform write distribution (
hash(user_id) mod N). Eliminates write hotspots. Downside: Breaks date range queries. - List Partitioning: Best for multi-tenant SaaS & data residency compliance (
country_code= EU, US). - Vertical Partitioning: Separates lean hot columns (
id,email) from heavy cold columns (bio,avatar_blob) to fit more rows per disk page in RAM. - Postgres Constraint Rule: Primary Keys and Unique Constraints MUST include the partition key column!
- Automation: Always deploy
pg_partmanto create future date range partitions automatically before they are needed.