github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/disttae/merge.go (about) 1 // Copyright 2022 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 disttae 16 17 import ( 18 "context" 19 "strings" 20 21 "github.com/matrixorigin/matrixone/pkg/catalog" 22 "github.com/matrixorigin/matrixone/pkg/common/mpool" 23 "github.com/matrixorigin/matrixone/pkg/container/batch" 24 "github.com/matrixorigin/matrixone/pkg/container/nulls" 25 "github.com/matrixorigin/matrixone/pkg/container/types" 26 "github.com/matrixorigin/matrixone/pkg/container/vector" 27 "github.com/matrixorigin/matrixone/pkg/fileservice" 28 "github.com/matrixorigin/matrixone/pkg/logutil" 29 "github.com/matrixorigin/matrixone/pkg/objectio" 30 "github.com/matrixorigin/matrixone/pkg/pb/api" 31 "github.com/matrixorigin/matrixone/pkg/vm/engine/disttae/logtailreplay" 32 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/blockio" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/mergesort" 34 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/options" 35 "github.com/matrixorigin/matrixone/pkg/vm/process" 36 ) 37 38 type cnMergeTask struct { 39 host *txnTable 40 // txn 41 snapshot types.TS // start ts, fixed 42 state *logtailreplay.PartitionState 43 proc *process.Process 44 45 // schema 46 version uint32 // version 47 colseqnums []uint16 // no rowid column 48 coltypes []types.Type // no rowid column 49 colattrs []string // no rowid column 50 sortkeyPos int // (composite) primary key, cluster by etc. -1 meas no sort key 51 sortkeyIsPK bool 52 53 doTransfer bool 54 55 // targets 56 targets []logtailreplay.ObjectInfo 57 58 // commit things 59 commitEntry *api.MergeCommitEntry 60 61 // auxiliaries 62 fs fileservice.FileService 63 64 blkCnts []int 65 blkIters []*StatsBlkIter 66 67 targetObjSize uint32 68 } 69 70 func newCNMergeTask( 71 ctx context.Context, 72 tbl *txnTable, 73 snapshot types.TS, 74 state *logtailreplay.PartitionState, 75 sortkeyPos int, 76 sortkeyIsPK bool, 77 targets []logtailreplay.ObjectInfo, 78 targetObjSize uint32, 79 ) (*cnMergeTask, error) { 80 proc := tbl.proc.Load() 81 attrs := make([]string, 0, len(tbl.seqnums)) 82 for i := 0; i < len(tbl.tableDef.Cols)-1; i++ { 83 attrs = append(attrs, tbl.tableDef.Cols[i].Name) 84 } 85 fs := proc.FileService 86 87 blkCnts := make([]int, len(targets)) 88 blkIters := make([]*StatsBlkIter, len(targets)) 89 for i, objInfo := range targets { 90 objInfo := objInfo 91 blkCnts[i] = int(objInfo.BlkCnt()) 92 93 loc := objInfo.ObjectLocation() 94 meta, err := objectio.FastLoadObjectMeta(ctx, &loc, false, fs) 95 if err != nil { 96 return nil, err 97 } 98 99 blkIters[i] = NewStatsBlkIter(&objInfo.ObjectStats, meta.MustDataMeta()) 100 } 101 102 return &cnMergeTask{ 103 host: tbl, 104 snapshot: snapshot, 105 state: state, 106 proc: proc, 107 version: tbl.version, 108 colseqnums: tbl.seqnums, 109 coltypes: tbl.typs, 110 colattrs: attrs, 111 sortkeyPos: sortkeyPos, 112 sortkeyIsPK: sortkeyIsPK, 113 targets: targets, 114 fs: fs, 115 blkCnts: blkCnts, 116 blkIters: blkIters, 117 118 targetObjSize: targetObjSize, 119 doTransfer: !strings.Contains(tbl.comment, catalog.MO_COMMENT_NO_DEL_HINT), 120 }, nil 121 } 122 123 func (t *cnMergeTask) DoTransfer() bool { 124 return t.doTransfer 125 } 126 func (t *cnMergeTask) GetObjectCnt() int { 127 return len(t.targets) 128 } 129 130 func (t *cnMergeTask) GetBlkCnts() []int { 131 return t.blkCnts 132 } 133 134 func (t *cnMergeTask) GetAccBlkCnts() []int { 135 accCnt := make([]int, 0, len(t.targets)) 136 acc := 0 137 for _, objInfo := range t.targets { 138 accCnt = append(accCnt, acc) 139 acc += int(objInfo.BlkCnt()) 140 } 141 return accCnt 142 } 143 144 func (t *cnMergeTask) GetBlockMaxRows() uint32 { 145 return options.DefaultBlockMaxRows 146 } 147 148 func (t *cnMergeTask) GetObjectMaxBlocks() uint16 { 149 return options.DefaultBlocksPerObject 150 } 151 152 func (t *cnMergeTask) GetTargetObjSize() uint32 { 153 return t.targetObjSize 154 } 155 156 func (t *cnMergeTask) GetSortKeyType() types.Type { 157 if t.sortkeyPos >= 0 { 158 return t.coltypes[t.sortkeyPos] 159 } 160 return types.Type{} 161 } 162 163 func (t *cnMergeTask) LoadNextBatch(ctx context.Context, objIdx uint32) (*batch.Batch, *nulls.Nulls, func(), error) { 164 iter := t.blkIters[objIdx] 165 if iter.Next() { 166 blk := iter.Entry() 167 // update delta location 168 obj := t.targets[objIdx] 169 blk.Sorted = obj.Sorted 170 blk.EntryState = obj.EntryState 171 blk.CommitTs = obj.CommitTS 172 if obj.HasDeltaLoc { 173 deltaLoc, commitTs, ok := t.state.GetBockDeltaLoc(blk.BlockID) 174 if ok { 175 blk.DeltaLoc = deltaLoc 176 blk.CommitTs = commitTs 177 } 178 } 179 return t.readblock(ctx, &blk) 180 } 181 return nil, nil, nil, mergesort.ErrNoMoreBlocks 182 } 183 184 func (t *cnMergeTask) GetCommitEntry() *api.MergeCommitEntry { 185 if t.commitEntry == nil { 186 return t.prepareCommitEntry() 187 } 188 return t.commitEntry 189 } 190 191 // impl DisposableVecPool 192 func (t *cnMergeTask) GetVector(typ *types.Type) (*vector.Vector, func()) { 193 v := t.proc.GetVector(*typ) 194 return v, func() { t.proc.PutVector(v) } 195 } 196 197 func (t *cnMergeTask) GetMPool() *mpool.MPool { 198 return t.proc.GetMPool() 199 } 200 201 func (t *cnMergeTask) HostHintName() string { return "CN" } 202 203 func (t *cnMergeTask) PrepareData(ctx context.Context) ([]*batch.Batch, []*nulls.Nulls, func(), error) { 204 r, release, d, e := t.readAllData(ctx) 205 return r, d, release, e 206 } 207 208 func (t *cnMergeTask) GetTotalSize() uint32 { 209 totalSize := uint32(0) 210 for _, obj := range t.targets { 211 totalSize += obj.OriginSize() 212 } 213 return totalSize 214 } 215 216 func (t *cnMergeTask) GetTotalRowCnt() uint32 { 217 totalRowCnt := uint32(0) 218 for _, obj := range t.targets { 219 totalRowCnt += obj.Rows() 220 } 221 return totalRowCnt 222 } 223 224 func (t *cnMergeTask) prepareCommitEntry() *api.MergeCommitEntry { 225 commitEntry := &api.MergeCommitEntry{} 226 commitEntry.DbId = t.host.db.databaseId 227 commitEntry.TblId = t.host.tableId 228 commitEntry.TableName = t.host.tableName 229 commitEntry.StartTs = t.snapshot.ToTimestamp() 230 for _, o := range t.targets { 231 commitEntry.MergedObjs = append(commitEntry.MergedObjs, o.ObjectStats.Clone().Marshal()) 232 } 233 t.commitEntry = commitEntry 234 // leave mapping to ReadMergeAndWrite 235 return commitEntry 236 } 237 238 func (t *cnMergeTask) PrepareNewWriter() *blockio.BlockWriter { 239 return mergesort.GetNewWriter(t.fs, t.version, t.colseqnums, t.sortkeyPos, t.sortkeyIsPK) 240 } 241 242 func (t *cnMergeTask) readAllData(ctx context.Context) ([]*batch.Batch, func(), []*nulls.Nulls, error) { 243 var cnt uint32 244 for _, t := range t.targets { 245 cnt += t.BlkCnt() 246 } 247 blkBatches := make([]*batch.Batch, 0, cnt) 248 blkDels := make([]*nulls.Nulls, 0, cnt) 249 releases := make([]func(), 0, cnt) 250 251 release := func() { 252 for _, r := range releases { 253 r() 254 } 255 } 256 257 for _, obj := range t.targets { 258 loc := obj.ObjectLocation() 259 meta, err := objectio.FastLoadObjectMeta(ctx, &loc, false, t.fs) 260 if err != nil { 261 release() 262 return nil, nil, nil, err 263 } 264 265 // read all blocks data in an object 266 var innerErr error 267 readBlock := func(blk objectio.BlockInfo, _ objectio.BlockObject) bool { 268 // update delta location 269 blk.Sorted = obj.Sorted 270 blk.EntryState = obj.EntryState 271 blk.CommitTs = obj.CommitTS 272 if obj.HasDeltaLoc { 273 deltaLoc, commitTs, ok := t.state.GetBockDeltaLoc(blk.BlockID) 274 if ok { 275 blk.DeltaLoc = deltaLoc 276 blk.CommitTs = commitTs 277 } 278 } 279 bat, delmask, releasef, err := t.readblock(ctx, &blk) 280 if err != nil { 281 innerErr = err 282 return false 283 } 284 285 blkBatches = append(blkBatches, bat) 286 releases = append(releases, releasef) 287 blkDels = append(blkDels, delmask) 288 return true 289 } 290 ForeachBlkInObjStatsList(false, meta.MustDataMeta(), readBlock, obj.ObjectStats) 291 // if err is found, bail out 292 if innerErr != nil { 293 release() 294 return nil, nil, nil, innerErr 295 } 296 } 297 298 return blkBatches, release, blkDels, nil 299 } 300 301 // readblock reads block data. there is no rowid column, no ablk 302 func (t *cnMergeTask) readblock(ctx context.Context, info *objectio.BlockInfo) (bat *batch.Batch, dels *nulls.Nulls, release func(), err error) { 303 // read data 304 bat, release, err = blockio.LoadColumns(ctx, t.colseqnums, t.coltypes, t.fs, info.MetaLocation(), t.proc.GetMPool(), fileservice.Policy(0)) 305 if err != nil { 306 return 307 } 308 309 // read tombstone on disk 310 if !info.DeltaLocation().IsEmpty() { 311 obat, byCN, delRelease, err2 := blockio.ReadBlockDelete(ctx, info.DeltaLocation(), t.fs) 312 if err2 != nil { 313 err = err2 314 return 315 } 316 defer delRelease() 317 if byCN { 318 dels = blockio.EvalDeleteRowsByTimestampForDeletesPersistedByCN(obat, t.snapshot, info.CommitTs) 319 } else { 320 dels = blockio.EvalDeleteRowsByTimestamp(obat, t.snapshot, &info.BlockID) 321 } 322 } 323 324 if dels == nil { 325 dels = nulls.NewWithSize(128) 326 } 327 deltalocDel := dels.Count() 328 // read tombstone in memory 329 iter := t.state.NewRowsIter(t.snapshot, &info.BlockID, true) 330 for iter.Next() { 331 entry := iter.Entry() 332 _, offset := entry.RowID.Decode() 333 dels.Add(uint64(offset)) 334 } 335 iter.Close() 336 if dels.Count() > 0 { 337 logutil.Infof("mergeblocks read block %v, %d deleted(%d from disk)", info.BlockID.ShortStringEx(), dels.Count(), deltalocDel) 338 } 339 340 bat.SetAttributes(t.colattrs) 341 return 342 }