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 }