Loading content...
Once you decide to distribute a database, the first fundamental question is: How do you divide the data?
The answer is fragmentation—the process of partitioning a database's relations (tables) into smaller pieces called fragments, each stored at one or more sites. The fragment becomes the unit of distribution: transactions access fragments, replication copies fragments, and queries are translated into operations on fragments.
Fragmentation is the foundation upon which all distributed database operations are built. A well-designed fragmentation scheme enables parallel query execution, reduces network traffic, and aligns data placement with access patterns. A poorly-designed scheme creates hotspots, cross-site joins, and performance bottlenecks.
By the end of this page, you will understand the three fragmentation strategies—horizontal, vertical, and hybrid—along with their correctness requirements, design algorithms, and practical trade-offs. You'll be able to evaluate fragmentation schemes for real-world distributed database deployments.
What is a Fragment?
A fragment is a subset of a relation that can be stored and managed independently. Formally, if R is a relation, we can decompose R into fragments R₁, R₂, ..., Rₙ where each Rᵢ contains a subset of R's data.
Fragmentation vs. Partitioning
The terms fragmentation and partitioning are often used interchangeably, though fragmentation is the classical distributed database term while partitioning is more common in modern systems. Both refer to dividing data into pieces distributed across nodes. We'll use "fragmentation" here to align with theoretical foundations.
Why Fragment?
Fragmentation serves multiple purposes:
Correctness Requirements
A valid fragmentation must satisfy three properties:
1. Completeness
If relation R is decomposed into fragments R₁, R₂, ..., Rₙ, every data item in R must appear in at least one fragment Rᵢ. No data is lost during fragmentation.
Mathematically: R = R₁ ∪ R₂ ∪ ... ∪ Rₙ
2. Reconstruction
It must be possible to reconstruct the original relation R from its fragments. This ensures the fragmentation is reversible—you can always recover the complete relation when needed.
For horizontal fragmentation: R = R₁ ∪ R₂ ∪ ... ∪ Rₙ (union) For vertical fragmentation: R = R₁ ⋈ R₂ ⋈ ... ⋈ Rₙ (natural join on key)
3. Disjointness (often desirable, not always required)
For storage efficiency, fragments should ideally be disjoint—each data item appears in exactly one fragment. This prevents redundant storage at the fragmentation level (replication is handled separately).
Mathematically: Rᵢ ∩ Rⱼ = ∅ for all i ≠ j
Fragmentation divides data into non-overlapping (or minimally overlapping) pieces. Replication copies pieces to multiple locations. These are orthogonal concerns: you can fragment without replicating, replicate without fragmenting, or both. Most production systems use both—fragment for parallelism, replicate for availability.
Horizontal fragmentation divides a relation by rows. Each fragment contains a subset of tuples, but all fragments have the same schema (all columns). Think of slicing a table horizontally—each slice is a valid table with the same column structure.
Formal Definition
Given relation R and selection predicates p₁, p₂, ..., pₙ, horizontal fragments are:
Where σ denotes the selection operation. For completeness, the predicates must cover all tuples:
p₁ ∨ p₂ ∨ ... ∨ pₙ ≡ true (for all tuples in R)
Example: Customer Table by Region
Consider a customers table for a global e-commerce platform:
123456789101112131415161718192021222324
-- Original tableCREATE TABLE customers ( customer_id INT PRIMARY KEY, name VARCHAR(100), email VARCHAR(100), region VARCHAR(50), country VARCHAR(50)); -- Horizontal fragments by region-- Fragment 1: North America (stored in US data center)Fragment_NA = σ(region = 'North America')(customers) -- Fragment 2: Europe (stored in EU data center)Fragment_EU = σ(region = 'Europe')(customers) -- Fragment 3: Asia-Pacific (stored in Singapore data center)Fragment_APAC = σ(region = 'Asia-Pacific')(customers) -- Fragment 4: Rest of World (stored in primary data center)Fragment_ROW = σ(region NOT IN ('North America', 'Europe', 'Asia-Pacific'))(customers) -- Reconstruction: UNION of all fragments returns original tablecustomers = Fragment_NA ∪ Fragment_EU ∪ Fragment_APAC ∪ Fragment_ROWTypes of Horizontal Fragmentation
Primary Horizontal Fragmentation
Fragments are defined using predicates on attributes of the relation itself. The example above uses region—an attribute of customers—as the fragmentation key.
Derived Horizontal Fragmentation
Fragments are defined based on relationships with other relations. For example, fragment orders based on the region of the associated customer:
This ensures related data is co-located: queries joining customers and orders can execute locally if both tables are fragmented consistently.
A poorly chosen fragmentation key creates hotspots (one fragment receives most traffic), cross-fragment queries (common queries span fragments), or skewed distribution (fragments of vastly different sizes). Key selection requires workload analysis—understanding which queries are common and how data is accessed.
Vertical fragmentation divides a relation by columns. Each fragment contains a subset of attributes but all tuples. Think of slicing a table vertically—each slice has fewer columns but the same number of rows.
Critical Requirement: Include Primary Key
Every vertical fragment must include the primary key (or a tuple identifier). Without the key, you cannot reconstruct the original relation—there's no way to know which attribute values belong together.
Formal Definition
Given relation R with attributes A = {a₁, a₂, ..., aₘ} and primary key K, vertical fragments are:
Where π denotes projection, and A₁ ∪ A₂ ∪ ... ∪ Aₙ = A (all attributes covered).
Reconstruction: R = R₁ ⋈ R₂ ⋈ ... ⋈ Rₙ (natural join on primary key)
1234567891011121314151617181920212223242526272829303132
-- Original table with wide schemaCREATE TABLE employees ( employee_id INT PRIMARY KEY, -- Core HR data name VARCHAR(100), department VARCHAR(50), hire_date DATE, -- Sensitive payroll data salary DECIMAL(10,2), bank_account VARCHAR(50), ssn VARCHAR(11), -- Large document resume_pdf BLOB, -- Audit fields created_at TIMESTAMP, updated_at TIMESTAMP); -- Vertical Fragment 1: Core HR (frequently accessed, HR systems)Fragment_HR = π(employee_id, name, department, hire_date)(employees) -- Vertical Fragment 2: Payroll (restricted access, payroll systems)Fragment_Payroll = π(employee_id, salary, bank_account, ssn)(employees) -- Vertical Fragment 3: Documents (archive storage, rarely accessed)Fragment_Docs = π(employee_id, resume_pdf)(employees) -- Vertical Fragment 4: Audit (compliance system)Fragment_Audit = π(employee_id, created_at, updated_at)(employees) -- Reconstruction: Natural join on employee_idemployees = Fragment_HR ⋈ Fragment_Payroll ⋈ Fragment_Docs ⋈ Fragment_AuditWhy Vertical Fragmentation?
Access Pattern Optimization: Most queries access only a subset of columns. Vertical fragmentation places frequently co-accessed columns together, reducing I/O.
Security Isolation: Sensitive columns (SSN, salary, medical data) can be isolated in fragments with restricted access.
Storage Tiering: Large, infrequently-accessed columns (BLOBs, CLOBs) stored on cheaper storage while frequently-accessed columns on fast SSD.
Cache Efficiency: Smaller fragments fit better in memory caches, improving hit rates.
Column-oriented databases (Vertica, ClickHouse, Amazon Redshift) essentially apply aggressive vertical fragmentation, storing each column separately. This maximizes compression, cache efficiency, and scan performance for analytical queries that aggregate few columns across many rows.
Hybrid fragmentation (also called mixed fragmentation) combines horizontal and vertical fragmentation. This allows exploiting benefits of both strategies—row-based distribution for locality and column-based splitting for access optimization.
Two Approaches
1. Horizontal-then-Vertical (HV)
First apply horizontal fragmentation to partition rows, then apply vertical fragmentation to each horizontal fragment:
2. Vertical-then-Horizontal (VH)
First apply vertical fragmentation to partition columns, then apply horizontal fragmentation to each vertical fragment:
123456789101112131415161718192021222324252627282930313233343536373839
-- Original: Large transaction history tableCREATE TABLE transactions ( txn_id BIGINT PRIMARY KEY, customer_id INT, region VARCHAR(20), txn_date TIMESTAMP, amount DECIMAL(12,2), status VARCHAR(20), description TEXT, -- Large text field receipt_image BLOB -- Large binary); -- Step 1: Horizontal fragmentation by region-- Creates regional subsets -- Step 2: Vertical fragmentation of each regional subset-- Fragment A: Frequently queried operational dataFragment_NA_Ops = π(txn_id, customer_id, txn_date, amount, status)( σ(region = 'NA')(transactions)) -- Fragment B: Large, rarely-accessed documentsFragment_NA_Docs = π(txn_id, description, receipt_image)( σ(region = 'NA')(transactions)) -- Same pattern for other regions...Fragment_EU_Ops = π(txn_id, customer_id, txn_date, amount, status)( σ(region = 'EU')(transactions)) Fragment_EU_Docs = π(txn_id, description, receipt_image)( σ(region = 'EU')(transactions)) -- Result: 2 regional × 2 column groups = 4 fragments per table-- Each fragment optimally placed:-- - Ops fragments on fast SSD in each region-- - Docs fragments on cheap archive storageReconstruction of Hybrid Fragments
Reconstruction combines the operations for both fragmentation types:
R = ⋃ᵢ (∪ₖ (Rᵢₖ ⋈ Rᵢₗ ⋈ ...))
When to Use Hybrid Fragmentation
Hybrid fragmentation offers maximum flexibility but also maximum complexity. Each additional fragmentation dimension multiplies the number of fragments, complicating placement, replication, and query routing. Use hybrid fragmentation when clear access patterns justify it, not as a default strategy.
Designing an optimal fragmentation scheme requires analyzing query workloads, access patterns, and data characteristics. Several algorithms guide this process:
Horizontal Fragmentation Design: Predicate-Based Partitioning
The goal is to define predicates that:
Algorithm: Simple Predicate Analysis
1234567891011121314151617
-- Example: Simple Predicate Analysis for orders table-- Collected predicates from query workload:p1: region = 'NA'p2: region = 'EU'p3: order_date >= '2024-01-01'p4: status = 'pending' -- Minterm predicates (all combinations):m1: region = 'NA' ∧ order_date >= '2024-01-01' ∧ status = 'pending'm2: region = 'NA' ∧ order_date >= '2024-01-01' ∧ status ≠ 'pending'm3: region = 'NA' ∧ order_date < '2024-01-01' ∧ status = 'pending'... (16 combinations for 4 boolean predicates) -- After workload analysis, group into fragments:Fragment_1: region = 'NA' ∧ status = 'pending' -- Active NA ordersFragment_2: region = 'EU' ∧ status = 'pending' -- Active EU ordersFragment_3: status ≠ 'pending' -- Historical (all regions)Vertical Fragmentation Design: Attribute Affinity
Vertical fragmentation groups attributes that are frequently accessed together. The attribute affinity measures how often two attributes appear in the same query.
Algorithm: Bond Energy Algorithm (BEA)
Example Affinity Matrix:
| Attribute | name | salary | ssn | resume | |
|---|---|---|---|---|---|
| name | — | 82 | 15 | 3 | 12 |
| 82 | — | 8 | 2 | 10 | |
| salary | 15 | 8 | — | 78 | 0 |
| ssn | 3 | 2 | 78 | — | 0 |
| resume | 12 | 10 | 0 | 0 | — |
Interpreting the Matrix:
name and email have high affinity (82 queries access both) → Group togethersalary and ssn have high affinity (78 queries access both) → Group togetherresume has low affinity with all others → Separate fragmentResulting Fragments:
Production systems increasingly automate fragmentation design. Query logs are analyzed to extract access patterns, and optimization algorithms suggest fragmentation schemes. Cloud data warehouses (BigQuery, Snowflake) even auto-cluster data based on observed query patterns. However, understanding the principles helps you evaluate and override automated decisions when needed.
Every fragmentation decision involves trade-offs. Understanding these helps you navigate design choices:
Fragment Size: Too Big vs. Too Small
| Aspect | Large Fragments | Small Fragments |
|---|---|---|
| Parallelism | Limited | High |
| Management overhead | Low | High |
| Load balancing | Coarse-grained | Fine-grained |
| Skew tolerance | Low | High |
| Query routing complexity | Low | High |
| Rebalancing cost | High | Low |
Fragmentation Granularity Guidelines
Rule of Thumb: Fragment size should be:
Typical Ranges:
Most distributed databases support online refragmentation—changing the fragmentation scheme while the system remains available. This is expensive but necessary as data volumes and access patterns evolve. Design with the expectation that you'll refragment at least once as your system matures.
After defining fragments, the next question is: Where do you place each fragment?
This is the allocation problem—assigning fragments to sites in a way that optimizes performance, availability, and resource utilization.
Allocation Considerations
Allocation Strategies
1. Full Replication
Every fragment at every site. Maximizes read availability and locality but:
2. No Replication (Partitioning Only)
Each fragment at exactly one site. Minimizes storage but:
3. Selective Replication
Each fragment replicated to K sites (where 1 < K < N). Balances:
| Strategy | Storage Cost | Read Availability | Write Complexity | Use Case |
|---|---|---|---|---|
| Full Replication | O(N × Data) | Maximum | O(N) per write | Small reference data, config |
| No Replication | O(Data) | Minimum | O(1) per write | Cost-sensitive, stateless apps |
| Selective (K=3) | O(3 × Data) | High | O(3) per write | Most production systems |
| Region-Aware (K=2 per region) | O(2R × Data/R) | High within region | O(2) per write | Multi-region deployments |
Place fragments that are frequently joined together on the same node. If customers and orders are always queried together, ensure each customer's orders are on the same node as that customer's data. This is 'co-location' or 'affinity-based placement' and eliminates distributed joins for common queries.
Data fragmentation is the foundation of distributed database design. Let's consolidate the key concepts:
What's Next
Fragmentation divides data, but for availability, you also need replication—maintaining copies of fragments across sites. The next page explores replication strategies: synchronous vs. asynchronous, primary-replica vs. multi-primary, and the consistency trade-offs each entails.
You now understand how distributed databases divide data through fragmentation. You can distinguish horizontal from vertical fragmentation, apply design algorithms to analyze workloads, and reason about allocation trade-offs. Next, we'll explore data replication for fault tolerance and performance.