Definition · Write cost of an indexFor a table carrying k secondary indexes, one insert performs k + 1 random writes: one for the row and one for each index page the new key lands on. On a device sustaining D random writes a second the insert rate is D/(k + 1), and the share of the bare rate is 1/(k + 1).
The same count holds for a delete, and an update counts once for every index whose key it changes.
Nothing in that definition is about how a particular engine is built. It is what it means for an index to be an index. A query planner can choose not to use an index; the writer has no such choice, because an index that skipped an insert would be wrong.
device 10 000 random writes a second
indexes k 0 1 2 3 4 5
writes/insert 1 2 3 4 5 6
inserts/s 10 000 5 000 3 333 2 500 2 000 1 667
share 1 1/2 1/3 1/4 1/5 1/6
100% 50.0% 33.3% 25.0% 20.0% 16.7%
Read the last row from left to right. The first index costs fifty percentage points, the second seventeen, the third eight, the fourth five. 1/(k + 1) falls fastest at the start, so the question “can we afford one more index?” has a different answer depending on how many there already are — and the cheapest place to add one is a table that already has several.
Example · Three indexes on a ten-thousand-write devicek = 3 makes an insert 4 random writes, so a device doing 10 000 random writes a second does 2 500 inserts a second: 25% of its bare rate. The device did not get slower and the rows did not get bigger. Three quarters of its write budget is now being spent keeping indexes correct.
Turning a target into a budget of indexes
Run the division the other way. If the workload needs T inserts a second on a device doing D random writes a second, the writes available per insert are D/T and the indexes you can afford are ⌊D/T⌋ − 1. At D = 10 000 and T = 2 500 that is 3. Raise the target by twenty per cent, to 3 000, and it falls to 2: the relation is a floor, so it moves in whole indexes, and every index is free until the division crosses an integer.
This is the arithmetic that makes an index a decision rather than an optimisation. An index that serves a query is worth it; an index that was added years ago for a report nobody runs is still being written on every insert, and the way to see that is to price it in the units above rather than in megabytes.
One honest caveat. An engine that buffers index updates — a change buffer, or an LSM's memtable — converts some of these random writes into sequential ones performed later, which is exactly the trade “Write Amplification in LSM Trees” prices. The k + 1 is the count of index pages that must eventually be written. When they are written, and how many times each, is a different question with a much larger answer.