Skip to content

storage: Fast approximate snapshot partitioning - #38094

Draft
peterdukelarsen wants to merge 1 commit into
pl/mysql-pk-partitioner-testsfrom
pl/mysql-snapshot-prefix-partition
Draft

storage: Fast approximate snapshot partitioning#38094
peterdukelarsen wants to merge 1 commit into
pl/mysql-pk-partitioner-testsfrom
pl/mysql-snapshot-prefix-partition

Conversation

@peterdukelarsen

Copy link
Copy Markdown
Contributor

Motivation

The boundary computation for parallel snapshotting was about as slow as the single-threaded snapshot in many cases, i.e.
Parallelized (~2h runtime):
Screenshot 2026-08-03 at 10 42 14 AM Screenshot 2026-08-03 at 10 42 49 AM

Single-threaded (~1h50m runtime):
Screenshot 2026-08-03 at 10 44 07 AM Screenshot 2026-08-03 at 10 44 27 AM

With this change we got rid of the boundary computation and were able to snapshot 1B rows in ~16m:
image image

Follow this anchor link for full details on the specs/data: https://app.notion.com/p/materialize/MySQL-Parallel-Snapshot-Smoke-Test-3a613f48d37b806fa311d1bfe9d4ec4c?source=copy_link#3a913f48d37b80a3bbb2dd05f6bc94c2

Description

Probes the values of a single-column string primary key using EXPLAIN and SELECT LIKE queries to compute approximate partitioning.

In slightly more detail we:

  1. Grab all of the unique first characters of the primary key strings and use EXPLAIN to estimate their row count
  2. For any character with a high row count we will redo the process one character deeper
  3. We continue stepping down into longer prefixes until we run out of a configured number of calls to make or we've resolved granular enough buckets to build partition boundaries
  4. Finally, we pick partition boundaries based on the total estimated row count (which could diverge from the real row count or the regular estimated row count by a good bit), and just walk the partitions in order computing boundary keys, which are just prefixes.

Downsides

  1. Complexity
  2. Won't work in all cases -- particularly any cases with extremely high cardinality characters in their prefixes could devolve. To work around this we'll follow up with implementing some caps on the number of queries we make and/or the time we spend, but obviously that will just prevent regression not make this work for all collections of string PKs.

Verification

  1. Deployed 777e7e8 to staging and snapshot 1B row table (August 3, around noon-3pm EDT)

Recreated from #37994 with an in-repo head branch so this PR can join the GitHub stack.

@peterdukelarsen
peterdukelarsen force-pushed the pl/mysql-snapshot-prefix-partition branch 2 times, most recently from a5d624c to 7888a17 Compare August 6, 2026 23:31
@peterdukelarsen
peterdukelarsen force-pushed the pl/mysql-snapshot-prefix-partition branch from 7888a17 to ec66765 Compare August 6, 2026 23:36
@peterdukelarsen
peterdukelarsen force-pushed the pl/mysql-snapshot-prefix-partition branch 2 times, most recently from a786a6f to 2b244fb Compare August 7, 2026 14:03
@peterdukelarsen
peterdukelarsen force-pushed the pl/mysql-snapshot-prefix-partition branch 2 times, most recently from 80601fb to b290345 Compare August 7, 2026 23:04
@peterdukelarsen
peterdukelarsen force-pushed the pl/mysql-snapshot-prefix-partition branch from b290345 to 09d39f3 Compare August 8, 2026 00:08
Replace the OFFSET-walking boundary discovery with the prefix-based
partitioner in mz-mysql-util, so discovery costs EXPLAIN index dives
instead of an O(rows) index pass.

Only string primary keys are supported. Integer keys, which the OFFSET
walk used to sample, now fall back to a single-worker whole-table read.
Prefixes of a numeric key do not order consistently with its values, so
they would need a separate numeric range splitter.

Boundaries are rendered as SQL literals via the server QUOTE() and
still pass the existing strict-monotonicity verification in each read
transaction.

The new mysql_source_snapshot_partition_min_rows dyncfg (default
50000) stops splitting below a minimum range size. Test configs set it
low so the tiny tables in mysql-cdc testdrive and parallel-workload
still exercise range reads.
@peterdukelarsen
peterdukelarsen force-pushed the pl/mysql-snapshot-prefix-partition branch from 09d39f3 to 9c36c30 Compare August 8, 2026 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant