Skip to content

keys-only Range optimization#21791

Open
nwnt wants to merge 1 commit into
etcd-io:mainfrom
nwnt:range-retrieval-changes-poc-and-benchmarking
Open

keys-only Range optimization#21791
nwnt wants to merge 1 commit into
etcd-io:mainfrom
nwnt:range-retrieval-changes-poc-and-benchmarking

Conversation

@nwnt
Copy link
Copy Markdown
Member

@nwnt nwnt commented May 22, 2026

A draft for #20386.

Technically, Range with --keys-only can avoid retrieving data from bbolt and instead return the keys from the in memory index b-tree. However, to support sorting and filtering by modified/created revisions or versions options, we can't return just the keys. Even though we still need to retrieve all the data when --sort-by=value is specified, luckily the rest of the metadata required by the sorting and filtering are available in the index b-tree.

This PR does the following:

  • Add keysOnly to mvcc.RangeOption, which is set when --keys-only is specified but not --sort-by=value.
  • Make treeIndex.Range return the list of created revisions and versions in addition to keys and modified revisions.
  • Make storeTxnCommon.rangeKeys use the newly added option to call the newly adjusted treeIndex.Range to create the RangeResult.kvs with CreateRevision and Version.

Filtering and sorting would work the same way, with the data and metadata they need to do their jobs.

@k8s-ci-robot
Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@k8s-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: nwnt
Once this PR has been reviewed and has the lgtm label, please assign fuweid for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@nwnt nwnt marked this pull request as ready for review May 22, 2026 11:23
@nwnt
Copy link
Copy Markdown
Member Author

nwnt commented May 22, 2026

converted to ready to run the CI tests

@nwnt nwnt changed the title index.Range returns all metadata keys-only Range optimization May 22, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.21%. Comparing base (27d5ef1) to head (7624a8a).
⚠️ Report is 45 commits behind head on main.

Additional details and impacted files
Files with missing lines Coverage Δ
server/etcdserver/txn/range.go 96.87% <100.00%> (+0.02%) ⬆️
server/storage/mvcc/index.go 93.47% <100.00%> (+0.09%) ⬆️
server/storage/mvcc/kv.go 40.00% <ø> (ø)
server/storage/mvcc/kvstore_txn.go 75.72% <100.00%> (+2.04%) ⬆️

... and 23 files with indirect coverage changes

@@           Coverage Diff           @@
##             main   #21791   +/-   ##
=======================================
  Coverage   70.20%   70.21%           
=======================================
  Files         426      427    +1     
  Lines       35241    35323   +82     
=======================================
+ Hits        24741    24801   +60     
- Misses       9107     9125   +18     
- Partials     1393     1397    +4     

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 27d5ef1...7624a8a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@serathius
Copy link
Copy Markdown
Member

Please fix tests

@nwnt nwnt force-pushed the range-retrieval-changes-poc-and-benchmarking branch 4 times, most recently from 32daca3 to bfc97ae Compare May 23, 2026 04:55
Comment thread server/storage/mvcc/kv.go Outdated
Limit int64
Rev int64
CountOnly bool
InMemoryKeysOnly bool
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What doesn "InMemory" mean in that context? Think "KeysOnly" should be good enough. Please make sure that mutually exclusive options like "KeysOnly" and "CountOnly".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed back to KeysOnly. I was thinking using the previous name might give the impression that it's the same value from the --keys-only flag, but in this case, it's actually a special case of it.

Should the mutual exclusivity logic be put in this PR or a separate one? I just had a look and the checking logic seems missing from the server, but anyway it's also orthogonal to this PR. But anyway let me what you think.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raised #21802 for the mutual exclusivity check.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just meant for code here. We should at maintain the same behavior. Do we have any tests covering this case?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

@serathius
Copy link
Copy Markdown
Member

/cc @fuweid @ahrtr

@k8s-ci-robot k8s-ci-robot requested review from ahrtr and fuweid May 23, 2026 08:43
@nwnt nwnt force-pushed the range-retrieval-changes-poc-and-benchmarking branch from bfc97ae to 568e776 Compare May 23, 2026 13:43
Comment thread server/storage/mvcc/kvstore_txn.go Outdated
@nwnt nwnt force-pushed the range-retrieval-changes-poc-and-benchmarking branch from 568e776 to 449b8b0 Compare May 24, 2026 04:16
Comment thread server/storage/mvcc/kvstore_txn.go Outdated
if len(keys) == 0 {
return &RangeResult{KVs: nil, Count: 0, Rev: curRev}, nil
}
cap := sliceCapWithLimit(int(ro.Limit), keys)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cap is a golang build-in function, let's try to use a different name, such as keyCount

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - I renamed them to cappedKeysCount and cappedEntriesCount.

Comment thread server/etcdserver/txn/range.go Outdated
Limit: limit,
Rev: r.Revision,
CountOnly: r.CountOnly,
KeysOnly: r.KeysOnly && r.SortTarget != pb.RangeRequest_VALUE,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two comments:

  • rename KeyOnly to FastKeyOnly
  • Why add r.SortTarget != pb.RangeRequest_VALUE here? I think we need to reuse function IsDefaultOrdering here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to FastKeysOnly.

We can't use IsDefaultOrdering because we can do all other ordering with the data stored in memory except in the case of ordering by value. That's why Range was modified to return the versions and modified revisions, and avoid retrieving them from bbolt. The only case we can't avoid bbolt is when --sort-by=value is specified.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't use IsDefaultOrdering because we can do all other ordering with the data stored in memory except in the case of ordering by value. That's why Range was modified to return the versions and modified revisions, and avoid retrieving them from bbolt. The only case we can't avoid bbolt is when --sort-by=value is specified.

OK. In that case, please add a comment.

Also I feel it's safer to add a feature gate, e.g. FastKeyOnlyRead, at least there is a way for users to disable it just in case.

Copy link
Copy Markdown
Member

@serathius serathius May 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the change is large enough or risky enough for feature gate. The we use the data already was present in index. We have good test coverage for range there is not much complication in code paths.

We just need the test for server preference between flags that are rejected on etcdctl side #21791 (comment)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the change is large enough or risky enough for feature gate. The we use the data already was present in index.

I am OK not to add a feature gate. If the data (revisions stuff) isn't consistent with bbolt, then it's a critical bug.

Comment thread server/storage/mvcc/kvstore_txn.go Outdated
if limit <= 0 || limit > len(revpairs) {
limit = len(revpairs)
}
cap := sliceCapWithLimit(int(ro.Limit), revpairs)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed accordingly

Signed-off-by: Nont <9658731+nwnt@users.noreply.github.com>
@nwnt nwnt force-pushed the range-retrieval-changes-poc-and-benchmarking branch from 449b8b0 to 7624a8a Compare May 25, 2026 15:00
@k8s-ci-robot
Copy link
Copy Markdown

@nwnt: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-etcd-integration-1-cpu-amd64 7624a8a link true /test pull-etcd-integration-1-cpu-amd64

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

Development

Successfully merging this pull request may close these issues.

4 participants