-
Notifications
You must be signed in to change notification settings - Fork 4.1k
sql: perform point key-value reads where possible #46758
Description
The KV API exposes both a ranged ScanRequest read operation and a point GetRequest read operation. Currently, SQL's row.Fetcher only ever uses ScanRequests, even when looking up a discrete set of keys. We should explore updating it to use GetRequests when possible.
For a multitude of reasons, we expect point KV operations to perform marginally better than ranged KV operations, even in cases where the SQL layer knows that the ranged operation operates over a fixed number of keys. Here's a non-exhaustive list of reasons why:
MVCCGet, unlikeMVCCScan, is able to use a prefix iterator, which allows it to make use of RocksDB/Pebble bloom filters. There may also be other wins at the storage layer, like avoiding prefetching- various data structures have optimizations and fast-paths for single-key operations (e.g. timestamp cache, latch manager, refresh span tracking)
- various code paths are simpler in the point operation case
- a point operation implies only needing a single key allocation instead of a start and end key allocation
- a point operation implies only needing to return up to a single result, which means that we can avoid some indirection in various places
We've known that these could add up to a performance win on simple workloads for some time. However, (to my knowledge) we've never actually made any measurements. Inspired by #46752, I hacked up a test using this patch. I then ran kv95 on a single-node cluster with and without the load-gen change that enables the use of GetRequest instead of ScanRequest. This led to the following improvement in throughput:
name old ops/sec new ops/sec delta
kv95 44.9k ± 3% 45.9k ± 2% +2.16% (p=0.056 n=6+6)
This seems significant enough to justify further investigation.
I think there's also a similar issue to be filed about DeleteRequest vs DeleteRangeRequest.
cc. @jordanlewis for triage.