Skip to content

DynamicCollection secondary index keys are not unique: deleting entries of a heavily duplicated value is quadratic #234

Open

Description

@mrdevrobot

Summary

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.

Activity

  1. added this to the v6 milestone on Oct 15, 2026
  2. added
    bugSomething isn't working
    severity/mediumSpace leak, inconsistency or failure in a narrow scenario
    priority/P2Should be in the next minor release if time allows
    area/indexingB-Tree and secondary indexes, index lifecycle
    on Oct 15, 2026
  3. CaffeinatedCoder commented on Oct 17, 2026

    @CaffeinatedCoder
    Collaborator

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/indexingB-Tree and secondary indexes, index lifecyclebugSomething isn't workingpackage/coreAffects BLite.Corepriority/P2Should be in the next minor release if time allowsseverity/mediumSpace leak, inconsistency or failure in a narrow scenariotriage

    Type

    No type

    Projects

    • Status
      Todo

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions