index: ordered _id index (roadmap item 2)
Give every Collection an implicit _id_ index (a normal Index with keys
[_id: 1]) so _id equality, $in, ranges and sorts stop depending on the
docs-map hash or a full scan. Kept out of the secondary indexes list, so
listIndexes/dropIndexes/createIndex and the log format are unchanged (no
index_create record, no double listing) and e2e3.js passes unmodified.
Maintained in upsert through the same reserve-then-insert protocol as
the secondaries, removed in evict_doc, and rebuilt after replay by
build_all_indexes alongside them (never maintained mid-replay, so a
failed add can't leave the index under-approximating). index.plan now
takes it as a separate argument. Its keys are canonical
(bson.encode_key gives int32 1, int64 1 and double 1.0 identical bytes),
so the serialization-guarded docs-map fast path (plan_id,
value_fast_path_safe and friends) is deleted.
Measured (tests/e2e/results/phase3.txt): sort({_id:-1}).limit(20) 6.2 ->
2.4 ms (2.3x slower than MongoDB -> parity); integer/string _id point
lookups, $in and ranges verified against the tree. Unit suite in all
three optimize modes, the crash pair, e2e3/e2e4/e2e6.
This commit is contained in:
@@ -644,31 +644,10 @@ fn scan_sorted(
|
||||
const filter_doc = bson.Document{ .arena = undefined, .pairs = filter };
|
||||
var n: usize = 0;
|
||||
|
||||
// _id_ fast path: the docs map is the _id index. Skipped when the
|
||||
// queried value's compare-equivalence class is serialization-ambiguous
|
||||
// (see index.plan_id).
|
||||
if (try index.plan_id(ctx.gpa, filter)) |id_plan| {
|
||||
var plan = id_plan;
|
||||
defer plan.deinit(ctx.gpa);
|
||||
// One scratch key, rebuilt per value: a key is never needed past its
|
||||
// own lookup.
|
||||
var key: std.ArrayListUnmanaged(u8) = .empty;
|
||||
defer key.deinit(ctx.gpa);
|
||||
for (plan.values) |v| {
|
||||
key.clearRetainingCapacity();
|
||||
try bson.write_serialized_value(v, ctx.gpa, &key);
|
||||
const doc = coll.docs.get(key.items) orelse continue;
|
||||
if (!try query.matches(ctx.gpa, &filter_doc, doc)) continue;
|
||||
if (out) |list| try list.append(ctx.gpa, doc);
|
||||
n += 1;
|
||||
if (lim != 0 and n >= lim) break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// Secondary-index plan: candidates in index order, re-filtered. The
|
||||
// returned ids alias the docs map keys, valid under the read lock.
|
||||
if (try index.plan(ctx.gpa, coll.indexes.items, filter, sort)) |p| {
|
||||
// Index plan (the implicit _id_ index first, then the secondaries):
|
||||
// candidates in index order, re-filtered. The returned ids alias the
|
||||
// docs map keys, valid under the read lock.
|
||||
if (try index.plan(ctx.gpa, &coll.id_index, coll.indexes.items, filter, sort)) |p| {
|
||||
var plan = p;
|
||||
defer plan.deinit(ctx.gpa);
|
||||
var ids: std.ArrayListUnmanaged([]const u8) = .empty;
|
||||
|
||||
Reference in New Issue
Block a user