Skip to content

Commit

Permalink
spanconfig: enable range coalescing by default
Browse files Browse the repository at this point in the history
Fixes #81008.

We built the basic infrastructure to coalesce ranges across table
boundaries back in 22.2 as part of #66063. We've enabled this
optimization for secondary tenants since then, but hadn't for the system
tenant because of two primary blockers:

- #93617: SHOW RANGES was broken by coalesced ranges.
- #84105: APIs to compute sizes for schema objects (used in our UI) was
  broken by coalesced ranges.

In both these cases we baked in assumptions about there being a minimum
of one-{table,index,partition}-per-range. These blockers didn't apply to
secondary tenants at the time since they didn't have access to SHOW
RANGES, nor the UI pages where these schema statistics were displayed.

We've addressed both these blockers in the 23.1 cycle as part of
bridging the compatibility between secondary tenants and yesteryear's
system tenant.
- #93644 revised SHOW RANGES and crdb_internal.ranges{,_no_leases}, both
  internally and its external UX, to accommodate ranges straddling
  table/database boundaries.
- #96223 re-worked our SpanStats API to work in the face of coalesced
  ranges, addressing #84105.

Release note (general change): CockroachDB would previously use separate
ranges for each table, index, or partition. This is no longer true --
it's possible now to have multiple tables, indexes, and partitions to
get packed into the same range. For users with many such "schema
objects", this will reduce the total range count in their clusters. This
is especially true if individual tables, indexes, or partitions are
smaller than the default configured maximum range size (controlled using
zone configs, specifically the range_max_bytes parameter).
We made this change to improve scalability with respect to the number of
schema objects, since the underlying range count now no longer a
bottleneck. Users upgrading from 22.2, once finalizing their upgrade,
may observe a round of range merges and snapshot transfers (to power
said range merges) as a result of this change. If users want to opt-out
of this optimization, they can use the following cluster setting:

  SET CLUSTER SETTING spanconfig.storage_coalesce_adjacent.enabled = false;
  • Loading branch information
irfansharif committed May 7, 2023
1 parent d737af9 commit 494b561
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 18 deletions.
2 changes: 1 addition & 1 deletion docs/generated/settings/settings-for-tenants.txt
Original file line number Diff line number Diff line change
Expand Up @@ -294,4 +294,4 @@ trace.opentelemetry.collector string address of an OpenTelemetry trace collecto
trace.snapshot.rate duration 0s if non-zero, interval at which background trace snapshots are captured tenant-rw
trace.span_registry.enabled boolean true if set, ongoing traces can be seen at https://<ui>/#/debug/tracez tenant-rw
trace.zipkin.collector string the address of a Zipkin instance to receive traces, as <host>:<port>. If no port is specified, 9411 will be used. tenant-rw
version version 1000023.1-6 set the active cluster version in the format '<major>.<minor>' tenant-rw
version version 1000023.1-8 set the active cluster version in the format '<major>.<minor>' tenant-rw
3 changes: 2 additions & 1 deletion docs/generated/settings/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
<tr><td><div id="setting-server-web-session-purge-ttl" class="anchored"><code>server.web_session.purge.ttl</code></div></td><td>duration</td><td><code>1h0m0s</code></td><td>if nonzero, entries in system.web_sessions older than this duration are periodically purged</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-server-web-session-timeout" class="anchored"><code>server.web_session_timeout</code></div></td><td>duration</td><td><code>168h0m0s</code></td><td>the duration that a newly created web session will be valid</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-spanconfig-bounds-enabled" class="anchored"><code>spanconfig.bounds.enabled</code></div></td><td>boolean</td><td><code>true</code></td><td>dictates whether span config bounds are consulted when serving span configs for secondary tenants</td><td>Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-spanconfig-storage-coalesce-adjacent-enabled" class="anchored"><code>spanconfig.storage_coalesce_adjacent.enabled</code></div></td><td>boolean</td><td><code>true</code></td><td>collapse adjacent ranges with the same span configs, for the ranges specific to the system tenant</td><td>Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-sql-auth-change-own-password-enabled" class="anchored"><code>sql.auth.change_own_password.enabled</code></div></td><td>boolean</td><td><code>false</code></td><td>controls whether a user is allowed to change their own password, even if they have no other privileges</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-sql-auth-resolve-membership-single-scan-enabled" class="anchored"><code>sql.auth.resolve_membership_single_scan.enabled</code></div></td><td>boolean</td><td><code>true</code></td><td>determines whether to populate the role membership cache with a single scan</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-sql-closed-session-cache-capacity" class="anchored"><code>sql.closed_session_cache.capacity</code></div></td><td>integer</td><td><code>1000</code></td><td>the maximum number of sessions in the cache</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
Expand Down Expand Up @@ -246,6 +247,6 @@
<tr><td><div id="setting-trace-snapshot-rate" class="anchored"><code>trace.snapshot.rate</code></div></td><td>duration</td><td><code>0s</code></td><td>if non-zero, interval at which background trace snapshots are captured</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-trace-span-registry-enabled" class="anchored"><code>trace.span_registry.enabled</code></div></td><td>boolean</td><td><code>true</code></td><td>if set, ongoing traces can be seen at https://&lt;ui&gt;/#/debug/tracez</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-trace-zipkin-collector" class="anchored"><code>trace.zipkin.collector</code></div></td><td>string</td><td><code></code></td><td>the address of a Zipkin instance to receive traces, as &lt;host&gt;:&lt;port&gt;. If no port is specified, 9411 will be used.</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-version" class="anchored"><code>version</code></div></td><td>version</td><td><code>1000023.1-6</code></td><td>set the active cluster version in the format &#39;&lt;major&gt;.&lt;minor&gt;&#39;</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
<tr><td><div id="setting-version" class="anchored"><code>version</code></div></td><td>version</td><td><code>1000023.1-8</code></td><td>set the active cluster version in the format &#39;&lt;major&gt;.&lt;minor&gt;&#39;</td><td>Serverless/Dedicated/Self-Hosted</td></tr>
</tbody>
</table>
8 changes: 8 additions & 0 deletions pkg/clusterversion/cockroach_versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,10 @@ const (
// indexes are enabled.
V23_2_PartiallyVisibleIndexes

// V23_2_EnableRangeCoalescingForSystemTenant enables range coalescing for
// the system tenant.
V23_2_EnableRangeCoalescingForSystemTenant

// *************************************************
// Step (1) Add new versions here.
// Do not add new versions to a patch release.
Expand Down Expand Up @@ -927,6 +931,10 @@ var rawVersionsSingleton = keyedVersions{
Key: V23_2_PartiallyVisibleIndexes,
Version: roachpb.Version{Major: 23, Minor: 1, Internal: 6},
},
{
Key: V23_2_EnableRangeCoalescingForSystemTenant,
Version: roachpb.Version{Major: 23, Minor: 1, Internal: 8},
},

// *************************************************
// Step (2): Add new versions here.
Expand Down
4 changes: 4 additions & 0 deletions pkg/server/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2206,6 +2206,10 @@ func TestAdminAPIDataDistribution(t *testing.T) {
firstServer := testCluster.Server(0)
sqlDB := sqlutils.MakeSQLRunner(testCluster.ServerConn(0))

// TODO(irfansharif): The data-distribution page and underyling APIs don't
// know how to deal with coalesced ranges. See #97942.
sqlDB.Exec(t, `SET CLUSTER SETTING spanconfig.storage_coalesce_adjacent.enabled = false`)

// Create some tables.
sqlDB.Exec(t, `CREATE DATABASE roachblog`)
sqlDB.Exec(t, `CREATE TABLE roachblog.posts (id INT PRIMARY KEY, title text, body text)`)
Expand Down
1 change: 1 addition & 0 deletions pkg/spanconfig/spanconfigstore/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ go_library(
importpath = "github.com/cockroachdb/cockroach/pkg/spanconfig/spanconfigstore",
visibility = ["//visibility:public"],
deps = [
"//pkg/clusterversion",
"//pkg/keys",
"//pkg/multitenant/tenantcapabilities",
"//pkg/roachpb",
Expand Down
20 changes: 12 additions & 8 deletions pkg/spanconfig/spanconfigstore/span_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"context"
"sort"

"github.com/cockroachdb/cockroach/pkg/clusterversion"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/settings"
Expand All @@ -34,15 +35,15 @@ var tenantCoalesceAdjacentSetting = settings.RegisterBoolSetting(
true,
)

// StorageCoalesceAdjacentSetting is a hidden cluster setting that
// controls whether we coalesce adjacent ranges outside of the
// secondary tenant keyspaces if they have the same span config.
// StorageCoalesceAdjacentSetting is a public cluster setting that controls
// whether we coalesce adjacent ranges outside of the secondary tenant keyspaces
// if they have the same span config.
var StorageCoalesceAdjacentSetting = settings.RegisterBoolSetting(
settings.SystemOnly,
"spanconfig.storage_coalesce_adjacent.enabled",
`collapse adjacent ranges with the same span configs for the ranges specific to the system tenant`,
false,
)
`collapse adjacent ranges with the same span configs, for the ranges specific to the system tenant`,
true,
).WithPublic()

// spanConfigStore is an in-memory data structure to store and retrieve
// SpanConfigs associated with a single span. Internally it makes use of a
Expand Down Expand Up @@ -104,7 +105,9 @@ func (s *spanConfigStore) forEachOverlapping(

// computeSplitKey returns the first key we should split on because of the
// presence a span config given a start and end key pair.
func (s *spanConfigStore) computeSplitKey(start, end roachpb.RKey) (roachpb.RKey, error) {
func (s *spanConfigStore) computeSplitKey(
ctx context.Context, start, end roachpb.RKey,
) (roachpb.RKey, error) {
sp := roachpb.Span{Key: start.AsRawKey(), EndKey: end.AsRawKey()}

// Generally split keys are going to be the start keys of span config entries.
Expand Down Expand Up @@ -152,7 +155,8 @@ func (s *spanConfigStore) computeSplitKey(start, end roachpb.RKey) (roachpb.RKey
// ranges.
systemTableUpperBound := keys.SystemSQLCodec.TablePrefix(keys.MaxReservedDescID + 1)
if roachpb.Key(rem).Compare(systemTableUpperBound) < 0 ||
!StorageCoalesceAdjacentSetting.Get(&s.settings.SV) {
!(StorageCoalesceAdjacentSetting.Get(&s.settings.SV) &&
s.settings.Version.IsActive(ctx, clusterversion.V23_2_EnableRangeCoalescingForSystemTenant)) {
return roachpb.RKey(match.span.Key), nil
}
} else {
Expand Down
1 change: 1 addition & 0 deletions pkg/spanconfig/spanconfigstore/span_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ func TestRandomized(t *testing.T) {
// span and asserts on all the properties above.
querySpan := getRandomSpan()
splitKeys := store.TestingSplitKeys(t,
ctx,
roachpb.RKey(querySpan.Key),
roachpb.RKey(querySpan.EndKey),
)
Expand Down
6 changes: 4 additions & 2 deletions pkg/spanconfig/spanconfigstore/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,13 @@ func (s *Store) NeedsSplit(ctx context.Context, start, end roachpb.RKey) (bool,
}

// ComputeSplitKey is part of the spanconfig.StoreReader interface.
func (s *Store) ComputeSplitKey(_ context.Context, start, end roachpb.RKey) (roachpb.RKey, error) {
func (s *Store) ComputeSplitKey(
ctx context.Context, start, end roachpb.RKey,
) (roachpb.RKey, error) {
s.mu.RLock()
defer s.mu.RUnlock()

return s.mu.spanConfigStore.computeSplitKey(start, end)
return s.mu.spanConfigStore.computeSplitKey(ctx, start, end)
}

// GetSpanConfigForKey is part of the spanconfig.StoreReader interface.
Expand Down
14 changes: 9 additions & 5 deletions pkg/spanconfig/spanconfigstore/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,24 @@ func (s *Store) TestingApplyInternal(

// TestingSplitKeys returns the computed list of range split points between
// [start, end).
func (s *Store) TestingSplitKeys(tb testing.TB, start, end roachpb.RKey) []roachpb.RKey {
func (s *Store) TestingSplitKeys(
tb testing.TB, ctx context.Context, start, end roachpb.RKey,
) []roachpb.RKey {
s.mu.RLock()
defer s.mu.RUnlock()

return s.mu.spanConfigStore.TestingSplitKeys(tb, start, end)
return s.mu.spanConfigStore.TestingSplitKeys(tb, ctx, start, end)
}

// TestingSplitKeys returns the computed list of range split points between
// [start, end).
func (s *spanConfigStore) TestingSplitKeys(tb testing.TB, start, end roachpb.RKey) []roachpb.RKey {
func (s *spanConfigStore) TestingSplitKeys(
tb testing.TB, ctx context.Context, start, end roachpb.RKey,
) []roachpb.RKey {
var splitKeys []roachpb.RKey
computeStart := start
for {
splitKey, err := s.computeSplitKey(computeStart, end)
splitKey, err := s.computeSplitKey(ctx, computeStart, end)
require.NoError(tb, err)
if splitKey == nil {
break
Expand Down Expand Up @@ -184,7 +188,7 @@ func TestDataDriven(t *testing.T) {
span := spanconfigtestutils.ParseSpan(t, spanStr)

start, end := roachpb.RKey(span.Key), roachpb.RKey(span.EndKey)
splitKeys := store.TestingSplitKeys(t, start, end)
splitKeys := store.TestingSplitKeys(t, ctx, start, end)
var b strings.Builder
for _, splitKey := range splitKeys {
b.WriteString(fmt.Sprintf("key=%s\n", string(splitKey)))
Expand Down
2 changes: 1 addition & 1 deletion pkg/spanconfig/testing_knobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ type TestingKnobs struct {
StoreDisableCoalesceAdjacent bool

// StoreIgnoreCoalesceAdjacentExceptions, if set, ignores the cluster settings
// spanconfig.{host,tenant}_coalesce_adjacent.enabled. It also allows
// spanconfig.{storage,tenant}_coalesce_adjacent.enabled. It also allows
// coalescing system database ranges for the host tenant.
StoreIgnoreCoalesceAdjacentExceptions bool

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ export class DataDistributionPage extends React.Component<
<BackToAdvanceDebug history={this.props.history} />
<section className="section">
<h1 className="base-heading">Data Distribution</h1>
<p style={{ maxWidth: 300, paddingTop: 10 }}>
Note: the data distribution render does not work with coalesced
ranges. To disable coalesced ranges (would increase range count),
run the following SQL statement:
</p>
<pre>
SET CLUSTER SETTING spanconfig.storage_coalesce_adjacent.enabled =
false;
</pre>
</section>
<section className="section">
<Loading
Expand Down

0 comments on commit 494b561

Please sign in to comment.