github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/table_scan/table_scan.go (about)

     1  // Copyright 2021-2023 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package table_scan
    16  
    17  import (
    18  	"bytes"
    19  	"time"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    22  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    23  	"github.com/matrixorigin/matrixone/pkg/txn/trace"
    24  	v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2"
    25  	"github.com/matrixorigin/matrixone/pkg/vm"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    27  )
    28  
    29  const argName = "table_scan"
    30  const maxBatchMemSize = colexec.DefaultBatchSize * 1024
    31  
    32  func (arg *Argument) String(buf *bytes.Buffer) {
    33  	buf.WriteString(argName)
    34  	buf.WriteString(": table_scan ")
    35  }
    36  
    37  func (arg *Argument) Prepare(proc *process.Process) (err error) {
    38  	arg.OrderBy = arg.Reader.GetOrderBy()
    39  	if arg.TopValueMsgTag > 0 {
    40  		arg.msgReceiver = proc.NewMessageReceiver([]int32{arg.TopValueMsgTag}, arg.GetAddress())
    41  	}
    42  	return nil
    43  }
    44  
    45  func (arg *Argument) Call(proc *process.Process) (vm.CallResult, error) {
    46  	var e error
    47  	start := time.Now()
    48  	txnOp := proc.TxnOperator
    49  	seq := uint64(0)
    50  	if txnOp != nil {
    51  		seq = txnOp.NextSequence()
    52  	}
    53  
    54  	trace.GetService().AddTxnDurationAction(
    55  		txnOp,
    56  		client.TableScanEvent,
    57  		seq,
    58  		arg.TableID,
    59  		0,
    60  		nil)
    61  
    62  	anal := proc.GetAnalyze(arg.GetIdx(), arg.GetParallelIdx(), arg.GetParallelMajor())
    63  	anal.Start()
    64  	defer func() {
    65  		anal.Stop()
    66  
    67  		cost := time.Since(start)
    68  
    69  		trace.GetService().AddTxnDurationAction(
    70  			txnOp,
    71  			client.TableScanEvent,
    72  			seq,
    73  			arg.TableID,
    74  			cost,
    75  			e)
    76  		v2.TxnStatementScanDurationHistogram.Observe(cost.Seconds())
    77  	}()
    78  
    79  	result := vm.NewCallResult()
    80  	//select {
    81  	//case <-proc.Ctx.Done():
    82  	//	result.Batch = nil
    83  	//	result.Status = vm.ExecStop
    84  	//	return result, proc.Ctx.Err()
    85  	//default:
    86  	//}
    87  	if err, isCancel := vm.CancelCheck(proc); isCancel {
    88  		e = err
    89  		return vm.CancelResult, err
    90  	}
    91  
    92  	if arg.buf != nil {
    93  		proc.PutBatch(arg.buf)
    94  	}
    95  
    96  	for {
    97  		// receive topvalue message
    98  		if arg.msgReceiver != nil {
    99  			msgs, _ := arg.msgReceiver.ReceiveMessage(false, proc.Ctx)
   100  			for i := range msgs {
   101  				msg, ok := msgs[i].(process.TopValueMessage)
   102  				if !ok {
   103  					panic("only support top value message in table scan!")
   104  				}
   105  				arg.Reader.SetFilterZM(msg.TopValueZM)
   106  			}
   107  		}
   108  		// read data from storage engine
   109  		bat, err := arg.Reader.Read(proc.Ctx, arg.Attrs, nil, proc.Mp(), proc)
   110  		if err != nil {
   111  			result.Status = vm.ExecStop
   112  			e = err
   113  			return result, err
   114  		}
   115  
   116  		if bat == nil {
   117  			if arg.tmpBuf != nil {
   118  				arg.buf = arg.tmpBuf
   119  				arg.tmpBuf = nil
   120  				break
   121  			} else {
   122  				result.Status = vm.ExecStop
   123  				e = err
   124  				return result, err
   125  			}
   126  		}
   127  
   128  		if bat.IsEmpty() {
   129  			continue
   130  		}
   131  
   132  		trace.GetService().TxnRead(
   133  			proc.TxnOperator,
   134  			proc.TxnOperator.Txn().SnapshotTS,
   135  			arg.TableID,
   136  			arg.Attrs,
   137  			bat)
   138  
   139  		bat.Cnt = 1
   140  		anal.S3IOByte(bat)
   141  		batSize := bat.Size()
   142  		arg.maxAllocSize = max(arg.maxAllocSize, batSize)
   143  
   144  		if arg.tmpBuf == nil {
   145  			arg.tmpBuf = bat
   146  			continue
   147  		}
   148  
   149  		tmpSize := arg.tmpBuf.Size()
   150  		if arg.tmpBuf.RowCount()+bat.RowCount() < colexec.DefaultBatchSize && tmpSize+batSize < maxBatchMemSize {
   151  			_, err := arg.tmpBuf.Append(proc.Ctx, proc.GetMPool(), bat)
   152  			proc.PutBatch(bat)
   153  			if err != nil {
   154  				e = err
   155  				return result, err
   156  			}
   157  			continue
   158  		}
   159  
   160  		arg.buf = arg.tmpBuf
   161  		arg.tmpBuf = bat
   162  		break
   163  	}
   164  
   165  	result.Batch = arg.buf
   166  	return result, nil
   167  }