-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
release-20.2: sql: implement sequence caching and cached sequence serial normalization #64690
release-20.2: sql: implement sequence caching and cached sequence serial normalization #64690
Conversation
@rafiss @RichardJCai any concerns about backporting this? Not sure if you were working with Jay when he made it. Andrew did but he's out this week. |
Richard is out until tomorrow, and I am out tomorrow and Thursday. I hadn't really looked into the implementation of this before. I don't know of a specific reason not to, apart from it being a new feature so not something that we'd generally backport. Are we supposed to be rigorously following this proposal? https://docs.google.com/document/d/1icfBB-WlzyStvl4t5cTYAV79RQGXvtCHOAvRV7EeC7g/edit If we are backporting, we'd need this too: #63548 |
Previously, incrementing sequences at a high throughput would result in many distributed writes to the KV layer due to MVCC. This has caused garbage collection problems in the past. This would occur in situations such as bulk importing data while using the sequence number as an id for each new row being added. This change allows clients to cache sequence numbers in their local session data. When the cache is empty, the sequence will be incremented once by the cache size * increment amount, which are both sequence options. Then, all the intermediate values will be cached locally on a node to be given out whenever the sequence is incremented. To accommodate schema changes, cached sequences values will be invalidated when new descriptor versions are seen by the cache. This invalidation can occur when old versions are seen as well to accommodate schema change rollbacks. Release note (sql change): Using the CACHE sequence option no longer results in an "unimplemented" error. The CACHE option is now fully implemented and will allow nodes to cache sequence numbers. A cache size of 1 means that there is no cache, and cache sizes of less than 1 are not valid.
Previously, there was no benchmark that tested the performance of concurrent increments to sequences. There was also no benchmark which compared sequence performance based on different cache sizes. This change adds a benchmark to measure performance based on the above criteria. Release note: None
Closes: cockroachdb#51259 Release note (sql change): The `serial_normalization` session variable can now be set to the value `sql_sequence_cached`. If this value is set, the cluster setting `sql.defaults.serial_sequences_cache_size` can be used to control the number of values to cache in a user's session with a default of 256. When the cache is empty, the the underlying sequence will only be incremened once to populate it. Using `sql_sequence_cached` will result in better performance than `sql_sequence` because the former will perform fewer distributed calls to increment sequences. However, cached seqences may result in large gaps between serial sequence numbers if a session terminates before using all the values in its cache.
Previously, cached sequences did not obey pg semantics with respect to exceeding bounds. For example, if there were a sequence with a cache size of 5 and max value of 2, calling nextval(...) would immediately cause an error due to exceeded bounds. According to postgres, nextval(...) should return 1, then 2, then finally return an error due to the max value of 2 being reached. This change alters sequence caching behavior to match the above semantics. Additionally, this change now makes it possible for sequences to exceed the bounds set by MAXVALUE and MINVALUE. This is because calling nextval(...) should be as fast as possible, and the fastest way to do this is to let nextval(...) always succeed on incrementing a sequence. Despite this, a user will never see any values that exceed a sequence's bounds. To make a sequence incrementable again after exceeding its bounds, there are two options: 1. The user changes the sequence's value by calling setval(...). 2. The user performs a schema change to alter the sequences MinValue or MaxValue. If the value of a sequence exceeds its bounds, it must be restored to the original MinValue or MaxValue in the same transaction as the schema change. This change adds code to handle case 2 above. Release note: None
737194e
to
42db57c
Compare
In 21.1 we added support for `CACHE` to sequences but we didn't add the logic to render that clause. Release note (bug fix): Render `CACHE` clause for sequences which use a cache.
Added the last commit. In terms of risk, maybe I should add a version gate on top of all of this stuff, so it's only active when activated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In terms of risk, maybe I should add a version gate on top of all of this stuff, so it's only active when activated.
I don't think that's allowed. That version wouldn't exist on other releases.
Reviewed 11 of 11 files at r1, 1 of 1 files at r2, 6 of 6 files at r3, 3 of 3 files at r4, 3 of 3 files at r5.
Reviewable status:complete! 1 of 0 LGTMs obtained (waiting on @jordanlewis)
Err, I really meant cluster setting, not version gate. |
I like that idea quite a bit. |
I don't think that this needs to get in at this point, I'm just going to close it. |
Backport 4/4 commits from #56954.
Backport 1/1 commits from #63548.
/cc @cockroachdb/release
sql: implement sequence caching
Previously, incrementing sequences at a high throughput
would result in many distributed writes to the KV layer
due to MVCC. This has caused garbage collection problems
in the past. This would occur in situations such as
bulk importing data while using the sequence number as an
id for each new row being added.
This change allows clients to cache sequence numbers in their local
session data. When the cache is empty, the sequence will be
incremented once by the cache size * increment amount, which are
both sequence options. Then, all the intermediate values will be
cached locally on a node to be given out whenever the sequence is
incremented.
To accommodate schema changes, cached sequences values will be
invalidated when new descriptor versions are seen by the cache.
This invalidation can occur when old versions are seen as well
to accommodate schema change rollbacks.
Release note (sql change): Using the CACHE sequence option no longer
results in an "unimplemented" error. The CACHE option is now fully
implemented and will allow nodes to cache sequence numbers. A cache
size of 1 means that there is no cache, and cache sizes of less than 1
are not valid.
sql: create benchmark for concurrent sequence increments
Previously, there was no benchmark that tested the performance
of concurrent increments to sequences. There was also no
benchmark which compared sequence performance based on
different cache sizes. This change updates a benchmark to measure
performance based on the above criteria.
Release note: None
sql: add serial normalization setting for cached sequences
Closes: #51259
Release note (sql change): The
serial_normalization
sessionvariable can now be set to the value
sql_sequence_cached
.Cached sequences will allow nodes to cache 256 sequence numbers
locally. The underlying sequence will only be incremened once (by
256 increments) when the cache is empty. Using
sql_sequence_cached
will result in better performance than
sql_sequence
because theformer will perform fewer distributed calls to increment sequences.
However, cached seqences may contribute to large gaps between
sequence numbers if cached values are lost due to errors or
node outages.
sql: make cached sequences bounds-related semantics match pg semantics
Previously, cached sequences did not obey pg semantics
with respect to exceeding bounds. For example, if there
were a sequence with a cache size of 5 and max value of 2,
calling nextval(...) would immediately cause an error due
to exceeded bounds. According to postgres, nextval(...)
should return 1, then 2, then finally return an error due
to the max value of 2 being reached. This change alters
sequence caching behavior to match the above semantics.
Additionally, this change now makes it possible for sequences
to exceed the bounds set by MAXVALUE and MINVALUE. This is
because calling nextval(...) should be as fast as possible,
and the fastest way to do this is to let nextval(...) always
succeed on incrementing a sequence. Despite this, a user
will never see any values that exceed a sequence's bounds.
To make a sequence incrementable again after exceeding its
bounds, there are two options:
or MaxValue. If the value of a sequence exceeds its bounds,
it must be restored to the original MinValue or MaxValue in
the same transaction as the schema change.
This change adds code to handle case 2 above.
Release note: None
Benchmark
Using
make bench PKG='./pkg/sql' BENCHES='BenchmarkSequenceIncrement' TESTFLAGS="--count=5 --benchmem" |& tee c{size} .txt
:Caching 256 values
For the other cache sizes I tested, the performance improvement is virtually the same as above.
c1.txt
c32.txt
c64.txt
c128.txt
c256.txt
c512.txt
c1024.txt