-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kvserver: use response data in the load-based splitter
We investigated why running YCSB Workload E results in a single hot range and we observed that range queries of the form SELECT * FROM table WHERE pkey >= A LIMIT B will result in all request spans having the same end key - similar to [A, range_end) - rather than end keys that take into account the specified LIMIT. Since the majority of request spans have the same end key, the load splitter algorithm cannot find a split key without too many contained and balance between left and right requests. A proposed solution is to use the response span rather than the request span, since the response span is more accurate in reflecting the keys that this request truly iterated over. We utilize the request span as well as the response's resume span to derive the key span that this request truly iterated over. Using response data (resume span) rather than just the request span in the load-based splitter (experimentally) allows the load-based splitter to find a split key under range query workloads (YCSB Workload E, KV workload with spans). Release note (ops change): We use response data rather than just the request span in the load-based splitter to pass more accurate data about the keys iterated over to the load splitter to find a suitable split key, enabling the load splitter to find a split key under heavy range query workloads.
- Loading branch information
Showing
3 changed files
with
239 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package kvserver | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/keys" | ||
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/spanset" | ||
"github.com/cockroachdb/cockroach/pkg/roachpb" | ||
"github.com/cockroachdb/cockroach/pkg/util/leaktest" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestReplicaGetTrueSpans(t *testing.T) { | ||
defer leaktest.AfterTest(t)() | ||
testCases := []struct { | ||
ba *roachpb.BatchRequest | ||
br *roachpb.BatchResponse | ||
expectedTrueSpans []roachpb.Span | ||
}{ | ||
{ | ||
ba: &roachpb.BatchRequest{ | ||
Requests: []roachpb.RequestUnion{ | ||
{ | ||
Value: &roachpb.RequestUnion_Get{ | ||
Get: &roachpb.GetRequest{ | ||
RequestHeader: roachpb.RequestHeader{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: roachpb.KeyMin, | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Value: &roachpb.RequestUnion_Scan{ | ||
Scan: &roachpb.ScanRequest{ | ||
RequestHeader: roachpb.RequestHeader{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(1000), | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Value: &roachpb.RequestUnion_Scan{ | ||
Scan: &roachpb.ScanRequest{ | ||
RequestHeader: roachpb.RequestHeader{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(1000), | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Value: &roachpb.RequestUnion_ReverseScan{ | ||
ReverseScan: &roachpb.ReverseScanRequest{ | ||
RequestHeader: roachpb.RequestHeader{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(1000), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
br: &roachpb.BatchResponse{ | ||
Responses: []roachpb.ResponseUnion{ | ||
{ | ||
Value: &roachpb.ResponseUnion_Get{ | ||
Get: &roachpb.GetResponse{ | ||
ResponseHeader: roachpb.ResponseHeader{ | ||
ResumeSpan: nil, | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Value: &roachpb.ResponseUnion_Scan{ | ||
Scan: &roachpb.ScanResponse{ | ||
ResponseHeader: roachpb.ResponseHeader{ | ||
ResumeSpan: nil, | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Value: &roachpb.ResponseUnion_Scan{ | ||
Scan: &roachpb.ScanResponse{ | ||
ResponseHeader: roachpb.ResponseHeader{ | ||
ResumeSpan: &roachpb.Span{ | ||
Key: keys.SystemSQLCodec.TablePrefix(113), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(1000), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
Value: &roachpb.ResponseUnion_ReverseScan{ | ||
ReverseScan: &roachpb.ReverseScanResponse{ | ||
ResponseHeader: roachpb.ResponseHeader{ | ||
ResumeSpan: &roachpb.Span{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(979), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
expectedTrueSpans: []roachpb.Span{ | ||
{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: roachpb.KeyMin, | ||
}, | ||
{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(1000), | ||
}, | ||
{ | ||
Key: keys.SystemSQLCodec.TablePrefix(100), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(113), | ||
}, | ||
{ | ||
Key: keys.SystemSQLCodec.TablePrefix(979), | ||
EndKey: keys.SystemSQLCodec.TablePrefix(1000), | ||
}, | ||
}, | ||
}, | ||
{ | ||
ba: &roachpb.BatchRequest{ | ||
Requests: []roachpb.RequestUnion{ | ||
{}, | ||
{}, | ||
}, | ||
}, | ||
br: &roachpb.BatchResponse{ | ||
Responses: []roachpb.ResponseUnion{ | ||
{}, | ||
}, | ||
}, | ||
expectedTrueSpans: nil, | ||
}, | ||
{ | ||
ba: &roachpb.BatchRequest{ | ||
Requests: []roachpb.RequestUnion{}, | ||
}, | ||
br: nil, | ||
expectedTrueSpans: nil, | ||
}, | ||
} | ||
for i, test := range testCases { | ||
trueSpanSet := getTrueSpans(context.Background(), test.ba, test.br) | ||
var trueSpans []roachpb.Span | ||
trueSpanSet.Iterate(func(spanAccess spanset.SpanAccess, spanScope spanset.SpanScope, span spanset.Span) { | ||
trueSpans = append(trueSpans, span.Span) | ||
}) | ||
assert.Equal(t, test.expectedTrueSpans, trueSpans, "True spans not equal in test %d", i) | ||
} | ||
} |