Use the Tablestore SDK for Go to split search index data and scan the splits in parallel for efficient large-scale export.
Prerequisites
Before you begin, complete the following preparations:
Install the Tablestore Go SDK and initialize a client.
Parallel scan requires Tablestore SDK for Go 1.6.0 or later. We recommend that you use the latest version.
Description
Parallel export first calls ComputeSplits to create a scan session and obtain the recommended concurrency. Then each concurrent worker calls ParallelScan with a unique CurrentParallelID and uses NextToken to read its split continuously. Parallel scan does not guarantee the order of the overall result set and is suitable for large exports that do not depend on result order. You can also set MaxParallel to 1 and CurrentParallelID to 0 for a single-worker scan. The code is simpler, and throughput is typically higher than Search but lower than a multi-worker scan.
Parallel scan does not support sorting or aggregation. Use Search if you need to sort results, perform aggregations, or return search results to end users.
Workers that use the same SessionId establish a data snapshot on the first ParallelScan call. Data inserted or updated during the task is not included in the snapshot. SessionId can be omitted, but changes such as server-side load balancing may cause a small number of duplicate rows. We recommend that you call ComputeSplits first and include the returned SessionId in subsequent requests.
Up to 10 parallel scan tasks can run concurrently on the same search index. For other limits, see Search index limits.
The following example starts multiple goroutines based on the recommended concurrency returned by ComputeSplits, assigns a unique CurrentParallelID to each worker, and reads all splits.
splits, err := client.ComputeSplits(
(&tablestore.ComputeSplitsRequest{}).
SetTableName("example_table").
SetSearchIndexSplitsOptions(tablestore.SearchIndexSplitsOptions{
IndexName: "example_index",
}),
)
if err != nil {
log.Fatal(err)
}
var waitGroup sync.WaitGroup
var mutex sync.Mutex
totalRows := 0
errors := make(chan error, splits.SplitsSize)
waitGroup.Add(int(splits.SplitsSize))
for workerID := int32(0); workerID < splits.SplitsSize; workerID++ {
currentWorkerID := workerID
go func() {
defer waitGroup.Done()
scanQuery := search.NewScanQuery().
SetQuery(&search.MatchAllQuery{}).
SetLimit(1000).
SetMaxParallel(splits.SplitsSize).
SetCurrentParallelID(currentWorkerID)
request := (&tablestore.ParallelScanRequest{}).
SetTableName("example_table").
SetIndexName("example_index").
SetScanQuery(scanQuery).
SetSessionId(splits.SessionId).
SetColumnsToGet(&tablestore.ColumnsToGet{
ReturnAllFromIndex: true,
})
for {
response, err := client.ParallelScan(request)
if err != nil {
errors <- err
return
}
// Process response.Rows here.
mutex.Lock()
totalRows += len(response.Rows)
mutex.Unlock()
if len(response.NextToken) == 0 {
return
}
request.SetScanQuery(scanQuery.SetToken(response.NextToken))
}
}()
}
waitGroup.Wait()
close(errors)
for err := range errors {
log.Fatal(err)
}
fmt.Println(totalRows)
Parameters
Create a scan session
|
Name |
Type |
Description |
|
TableName (required) |
string |
The name of the data table. |
|
IndexName (required) |
string |
The name of the search index. |
Parallel scan request
|
Name |
Type |
Description |
|
TableName (required) |
string |
The name of the data table. |
|
IndexName (required) |
string |
The name of the search index. |
|
ScanQuery (required) |
search.ScanQuery |
The scan condition and concurrency configuration. |
|
SessionId (optional) |
[]byte |
The session ID returned by ComputeSplits. We recommend that you specify this parameter to use the same data snapshot throughout the scan. |
|
ColumnsToGet (optional) |
*tablestore.ColumnsToGet |
The return-column configuration. If omitted, only primary key columns are returned. ParallelScan does not support ReturnAll. |
|
TimeoutMs (optional) |
*int32 |
The request timeout period in milliseconds. |
Scan configuration
|
Name |
Type |
Description |
|
Query (required) |
search.Query |
The scan condition. Non-vector query types supported by Search are supported. |
|
Limit (optional) |
int32 |
The maximum number of rows returned per request. Default value: 2,000. We recommend that you retain the default. The server allows a value up to 10,000, but a larger value increases request latency and resource usage. |
|
MaxParallel (optional) |
int32 |
The total number of workers. Default value: 1. The value cannot exceed SplitsSize returned by ComputeSplits. |
|
CurrentParallelID (optional) |
int32 |
The current worker ID. This parameter is required when MaxParallel is greater than 1. Worker IDs must be unique and fall within [0, MaxParallel). |
|
Token (optional) |
[]byte |
The NextToken value returned by the previous response. |
|
AliveTime (optional) |
int32 |
The maximum interval between two pagination requests, in seconds. Valid values: 1 to 600. Default value: 60. We recommend that you retain the default. Each successful data request refreshes the validity period. |
Return-column configuration
|
Name |
Type |
Description |
|
Columns (optional) |
[]string |
The search index fields to return. A field that exists only in the data table and is not included in the search index cannot be returned. |
|
ReturnAllFromIndex (optional) |
bool |
Specifies whether to return all fields from the search index. Default value: false. If this parameter is true, you do not need to specify Columns. |
|
ReturnAll (optional) |
bool |
Parallel scan does not support this parameter. Do not set it to true. |
Schema changes that switch indexes, server failover, or load balancing may invalidate a session early and return OTSSessionExpired. Client network errors may also interrupt a scan. If such an error occurs, discard the incomplete results, call ComputeSplits again, and restart the entire scan task from the beginning.
Response
Split information
|
Name |
Type |
Description |
|
SessionId |
[]byte |
The task session ID used to scan the same data snapshot. |
|
SplitsSize |
int32 |
The maximum supported concurrency for the search index. |
Scan result
|
Name |
Type |
Description |
|
Rows |
[]*tablestore.Row |
The rows returned by the current scan. |
|
NextToken |
[]byte |
The token for the next page. Continue scanning the current split if the value is not empty. |