Part of epic #488. Depends on Phase 1 (MV-1).
Goal
An MV can declare its own shard count and replication factor, separate from the base table. Useful when the MV's access pattern differs sharply from the base (e.g. base is write-heavy single-PK, MV is read-heavy with a different partitioning).
Files
internal/placement/placement.go (+80) — extend PlacementCatalog to support per-MV placement (today: one placement per cluster covers all logical shards uniformly)
internal/cluster/manager.go (+100) — open MV shards alongside base; existing mux carries the extra raft groups
pkg/types/types.go MVDescriptor (+15) — fields Shards int, ReplicationFactor int (defaults to base when zero)
internal/sql/parser.go (+40) — extend CREATE MATERIALIZED VIEW v WITH SHARDS=N REPLICATION_FACTOR=R AS SELECT ... syntax
docs/adr/0003-materialized-views.md update — note the trade-off (storage overhead vs. read-amplification reduction)
Reuse
cluster.Open shard-opening loop.
placement.DefaultPlacementWithReplicationFactor (internal/placement/placement.go:194) as template.
DoD
Out of scope
- Dynamic placement migration (moving MV shards across nodes at runtime).
- Per-MV strategy override (token-range vs. random-hash) — assume same as base for v1.
Tier
T3 (~250 LOC; touches placement model and cluster manager startup).
Part of epic #488. Depends on Phase 1 (MV-1).
Goal
An MV can declare its own shard count and replication factor, separate from the base table. Useful when the MV's access pattern differs sharply from the base (e.g. base is write-heavy single-PK, MV is read-heavy with a different partitioning).
Files
internal/placement/placement.go(+80) — extendPlacementCatalogto support per-MV placement (today: one placement per cluster covers all logical shards uniformly)internal/cluster/manager.go(+100) — open MV shards alongside base; existing mux carries the extra raft groupspkg/types/types.goMVDescriptor (+15) — fieldsShards int,ReplicationFactor int(defaults to base when zero)internal/sql/parser.go(+40) — extendCREATE MATERIALIZED VIEW v WITH SHARDS=N REPLICATION_FACTOR=R AS SELECT ...syntaxdocs/adr/0003-materialized-views.mdupdate — note the trade-off (storage overhead vs. read-amplification reduction)Reuse
cluster.Openshard-opening loop.placement.DefaultPlacementWithReplicationFactor(internal/placement/placement.go:194) as template.DoD
CREATE MATERIALIZED VIEW v WITH SHARDS=12 REPLICATION_FACTOR=2 AS SELECT ...opens 12 raft groups distinct from base's shards.WITH SHARDS / REPLICATION_FACTOR— they get default placement (derived from base).go test -race -count=1 ./internal/cluster/ ./internal/placement/clean.SHARDS=12 REPLICATION_FACTOR=2, base with default 24×3.Out of scope
Tier
T3 (~250 LOC; touches placement model and cluster manager startup).