60–100% rows
Large changed fraction
UPDATE loses selectivity while retaining per-row versioning and logging.
BULK MUTATION · CTAS · ATOMIC SWAP
UPDATE appears surgical, yet may create row versions, logs, index work and cleanup. Read–transform–new table can scan and write sequentially, then swap once.
WHEN THE COST FLIPS
There is no universal threshold. Benchmark the real workload, but these patterns raise mutation cost.
60–100% rows
UPDATE loses selectivity while retaining per-row versioning and logging.
secondary indexes
Changed values require repeated index-entry maintenance.
PostgreSQL · InnoDB
Old snapshots require prior row versions and later cleanup.
primary + replicas
Every mutation must be recoverable and replicated.
parts · compression
Scattered row changes can become compressed-part rewrites.
partition · sort · encoding
Rebuilding transforms and reorganises in one pass.
poor locality
UPDATE may jump pages while CTAS reads and writes sequentially.
vacuum · purge · merge
Cost continues into scans, caches, backups and cleanup.
join · cast · normalize
A set-oriented pipeline writes the intended destination directly.
PHYSICAL WORK
Compare bytes, logs, indexes, locks, cleanup and replica impact—not elapsed time alone.
INTERACTIVE COST MODEL
This builds intuition rather than replacing a benchmark.
LIVE MARIADB LAB · MEASURE ONE BOUNDARY AT A TIME
The source table is experiment setup. Its time is reported separately and excluded from the primary comparison.
Build the indexed source and record its checksum before both paths begin.
Copy source into a working table first, then time only the UPDATE statement.
Time the source scan, CASE transformation and write into a new table.
CONNECTING TO MARIADB…
Choose a bounded size and repeat runs; the first can include cold-cache and page-allocation effects.
UPDATE copy_table
SET amount = amount * 2 + 7,
segment = MOD(segment + 1, 12)
WHERE MOD(id, 100) < :changed_percent;CREATE TEMPORARY TABLE new_table AS
SELECT id,
CASE WHEN changed THEN amount * 2 + 7 ELSE amount END amount,
CASE WHEN changed THEN MOD(segment + 1, 12) ELSE segment END segment
FROM source_table;UPDATE only ÷ transform → new table. Copy and index times remain visible for transparency but are not mixed into this ratio.
Not yet run
1 · If UPDATE alone is slower
Per-row mutation work, including index maintenance and logging, exceeded scan-transform-write for this workload, even before copy time.
2 · If UPDATE remains faster
Increase changed fraction or indexes and rerun. The crossover depends on engine, cache, row width and storage.
3 · Do not trust one elapsed time
Repeat, inspect the median and observe bytes, logs and locks in production. This lab teaches measurement boundaries—not a universal winner.
ENGINE-AWARE SQL
Always inspect engine transaction, lock, replication and DDL semantics.
CREATE TABLE customer_new AS SELECT id, normalize_email(email) email FROM customer; CREATE INDEX ON customer_new(id); ANALYZE customer_new; -- validate, catch up concurrent changes, then plan transactional cutover
CREATE TABLE customer_new LIKE customer; INSERT INTO customer_new SELECT id, LOWER(TRIM(email)) FROM customer; RENAME TABLE customer TO customer_old, customer_new TO customer;
CREATE TABLE events_new AS events; INSERT INTO events_new SELECT * REPLACE (transform(x) AS x) FROM events; -- validate then exchange tables, or replace only affected partitions
CREATE TABLE facts_new AS SELECT * REPLACE (standardize(amount) AS amount) FROM facts; -- validate and swap names in a controlled transaction
DECISION GUIDE
Choose the method that preserves correctness and recovery—not merely apparent speed.
| Situation | Likely choice | Reason |
|---|---|---|
| <5–10% rows | UPDATE | Selective work can beat a complete rewrite. |
| Most rows + many indexes | Benchmark rebuild | Logging and index amplification may dominate. |
| Partition/sort/encoding changes | Rebuild/partition replace | The physical layout itself changes. |
| Continuous writes | Online migration | CTAS alone misses post-snapshot changes. |
| Low free disk | Chunked UPDATE | Rebuild temporarily needs two copies plus indexes. |
| Strict rollback | Build–validate–swap | The old table remains a rollback target. |
With concurrent writes, define snapshot boundaries, CDC catch-up, validation, cutover locking and rollback—or the fast table may lose data.
SAFE REBUILD
Adapt this checklist to the engine and SLA.