You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
DynamicCollection secondary index keys are not unique: deleting entries of a heavily duplicated value is quadratic #234
DynamicCollection secondary B-Tree indexes store the raw key with no document id appended (DynamicCollection.cs, index insert and delete paths). Typed collections store [user key][document id], so every typed index key is unique. With non-unique dynamic keys, removing one entry of a heavily duplicated value has to search every leaf that holds that value for the exact (key, location) pair.
Since #232 (the fix for #213) that search is correct, but it is linear in the number of leaves holding the value. Deleting N copies of one key is therefore quadratic. The #232 review measured 20,000 entries on 16 KB pages deleted in random order: 5.9 s when they all share one key, against 0.12 s with distinct keys. Low-cardinality indexes (status, bool, type) are affected on every delete, and on every update that changes the indexed value.
#232 removes the most common trigger: an update that leaves an indexed value and the document's location unchanged no longer deletes and re-inserts the entry.
Proposal
Store dynamic secondary keys as [user key][document id], as CollectionSecondaryIndex already does, so every entry is unique and a delete descends straight to it. Range queries keep using the composite boundaries the typed indexes already use.
Old dynamic indexes are not in this format, so the change needs a KeyFormat bump and a rebuild on open, like the decimal-key migration (NeedsKeyFormatMigration). That is why this is planned for v6, together with #212 (prefix-free key encoding), which also needs a rebuild.
Alternative
Break ties on the document location during descent. This needs no format change, but internal separators would have to carry the location, which is itself a node format change.
The DynamicCollection store model (DuplicateDeletes_ScaleLikeNLogN in tests/BLite.Tests/Oracles/DynamicStoreModelTests.cs, #272) measures this: one DeleteBulkAsync of 1,500 and 12,000 documents sharing one indexed value takes x38 to x40 longer for 8x the documents (distinct values: x10.5), and it carries the row as a known candidate linked to this issue.
Activity
CaffeinatedCoder commentedon Oct 17, 2026
The DynamicCollection store model (
DuplicateDeletes_ScaleLikeNLogNintests/BLite.Tests/Oracles/DynamicStoreModelTests.cs, #272) measures this: oneDeleteBulkAsyncof 1,500 and 12,000 documents sharing one indexed value takes x38 to x40 longer for 8x the documents (distinct values: x10.5), and it carries the row as a known candidate linked to this issue.