Skip to main content

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples in this guide work on VillageSQL. Install Now →
Partitioning splits one logical table into multiple physical segments. MySQL routes rows to partitions based on a partitioning expression, and queries that filter on the partition key can skip entire partitions — an optimization called partition pruning. Partitioning requires the InnoDB or NDB storage engine.

When Partitioning Helps

Partition pruning delivers real gains when:
  • The table is too large to fit in the buffer pool and queries consistently filter on the partition key
  • You regularly drop old data — ALTER TABLE t DROP PARTITION p_old is instant vs. a slow DELETE
Partitioning does NOT help when:
  • Queries don’t filter on the partition key (all partitions must be scanned)
  • The table fits comfortably in memory
  • You’re trying to replace proper indexing — a good index on a non-partitioned table often outperforms a partitioned table without matching indexes

RANGE Partitioning

Rows are assigned to partitions based on whether the partition key falls within a range. The most common use case is date-based archival.
Always include a MAXVALUE partition to catch rows that don’t fit any defined range. Without it, inserts outside the defined ranges fail with an error. Add a new partition:
Drop old data instantly:

LIST Partitioning

Rows are assigned based on exact values in the partition key.
Inserts with a region not listed in any partition fail. Use LIST COLUMNS for string columns — LIST alone only supports integer expressions.

HASH and KEY Partitioning

HASH and KEY distribute rows evenly across a fixed number of partitions. They don’t support partition pruning by value but can improve concurrent write throughput by spreading rows across partitions.

Partition Pruning

Pruning only activates when the WHERE clause filters directly on the partition expression. With RANGE COLUMNS (created_at), filtering on created_at prunes correctly:
To verify pruning, run EXPLAIN and check the partitions column:
If partitions shows only one or a few partition names, pruning is working. If it shows all partitions, the filter isn’t being applied.

Partitioning Constraints

  • Every unique key (including the primary key) must include all columns in the partitioning expression. If you want to partition by created_at, every unique key must contain created_at — you can’t add a partition to a table with a standalone PRIMARY KEY (id) unless you first change it to PRIMARY KEY (id, created_at).
  • FOREIGN KEY constraints are not supported on partitioned tables in MySQL.
  • A table can have a maximum of 8192 partitions (MySQL 8.0+).

Partitioning vs Indexing

Start with indexing. Add partitioning only when you have a demonstrated performance problem on a large table and a clear partition key that matches your query patterns.

Frequently Asked Questions

Can I partition an existing table?

Yes, with ALTER TABLE:
This rewrites the table, which can take significant time and disk space on large tables.

How do I check which partition a row is in?

To see which partition a specific row would go to, use EXPLAIN PARTITIONS with a WHERE clause matching that row.

Troubleshooting

See also