github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/hints.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package embedded 15 16 import ( 17 "github.com/whtcorpsinc/BerolinaSQL/ast" 18 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 19 "github.com/whtcorpsinc/milevadb/ekv" 20 utilhint "github.com/whtcorpsinc/milevadb/soliton/hint" 21 "github.com/whtcorpsinc/milevadb/stochastikctx" 22 ) 23 24 // GenHintsFromPhysicalCauset generates hints from physical plan. 25 func GenHintsFromPhysicalCauset(p Causet) []*ast.BlockOptimizerHint { 26 var hints []*ast.BlockOptimizerHint 27 switch pp := p.(type) { 28 case *Explain: 29 return GenHintsFromPhysicalCauset(pp.TargetCauset) 30 case *UFIDelate: 31 hints = genHintsFromPhysicalCauset(pp.SelectCauset, utilhint.TypeUFIDelate) 32 case *Delete: 33 hints = genHintsFromPhysicalCauset(pp.SelectCauset, utilhint.TypeDelete) 34 case PhysicalCauset: 35 hints = genHintsFromPhysicalCauset(pp, utilhint.TypeSelect) 36 } 37 return hints 38 } 39 40 func getBlockName(tblName perceptron.CIStr, asName *perceptron.CIStr) perceptron.CIStr { 41 if asName != nil && asName.L != "" { 42 return *asName 43 } 44 return tblName 45 } 46 47 func extractBlockAsName(p PhysicalCauset) (*perceptron.CIStr, *perceptron.CIStr) { 48 if len(p.Children()) > 1 { 49 return nil, nil 50 } 51 switch x := p.(type) { 52 case *PhysicalBlockReader: 53 ts := x.BlockCausets[0].(*PhysicalBlockScan) 54 if ts.BlockAsName.L != "" { 55 return &ts.DBName, ts.BlockAsName 56 } 57 return &ts.DBName, &ts.Block.Name 58 case *PhysicalIndexReader: 59 is := x.IndexCausets[0].(*PhysicalIndexScan) 60 if is.BlockAsName.L != "" { 61 return &is.DBName, is.BlockAsName 62 } 63 return &is.DBName, &is.Block.Name 64 case *PhysicalIndexLookUpReader: 65 is := x.IndexCausets[0].(*PhysicalIndexScan) 66 if is.BlockAsName.L != "" { 67 return &is.DBName, is.BlockAsName 68 } 69 return &is.DBName, &is.Block.Name 70 } 71 return nil, nil 72 } 73 74 func getJoinHints(sctx stochastikctx.Context, joinType string, parentOffset int, nodeType utilhint.NodeType, children ...PhysicalCauset) (res []*ast.BlockOptimizerHint) { 75 for _, child := range children { 76 blockOffset := child.SelectBlockOffset() 77 if blockOffset == -1 { 78 continue 79 } 80 var dbName, blockName *perceptron.CIStr 81 if child.SelectBlockOffset() != parentOffset { 82 hintBlock := sctx.GetStochastikVars().CausetAppendSelectBlockAsName[child.SelectBlockOffset()] 83 // For sub-queries like `(select * from t) t1`, t1 should belong to its surrounding select causet. 84 dbName, blockName, blockOffset = &hintBlock.DBName, &hintBlock.BlockName, parentOffset 85 } else { 86 dbName, blockName = extractBlockAsName(child) 87 } 88 if blockName == nil { 89 continue 90 } 91 res = append(res, &ast.BlockOptimizerHint{ 92 QBName: utilhint.GenerateQBName(nodeType, blockOffset), 93 HintName: perceptron.NewCIStr(joinType), 94 Blocks: []ast.HintBlock{{DBName: *dbName, BlockName: *blockName}}, 95 }) 96 break 97 } 98 return res 99 } 100 101 func genHintsFromPhysicalCauset(p PhysicalCauset, nodeType utilhint.NodeType) (res []*ast.BlockOptimizerHint) { 102 for _, child := range p.Children() { 103 res = append(res, genHintsFromPhysicalCauset(child, nodeType)...) 104 } 105 switch pp := p.(type) { 106 case *PhysicalBlockReader: 107 tbl := pp.BlockCausets[0].(*PhysicalBlockScan) 108 res = append(res, &ast.BlockOptimizerHint{ 109 QBName: utilhint.GenerateQBName(nodeType, pp.blockOffset), 110 HintName: perceptron.NewCIStr(HintUseIndex), 111 Blocks: []ast.HintBlock{{DBName: tbl.DBName, BlockName: getBlockName(tbl.Block.Name, tbl.BlockAsName)}}, 112 }) 113 if tbl.StoreType == ekv.TiFlash { 114 res = append(res, &ast.BlockOptimizerHint{ 115 QBName: utilhint.GenerateQBName(nodeType, pp.blockOffset), 116 HintName: perceptron.NewCIStr(HintReadFromStorage), 117 HintData: perceptron.NewCIStr(ekv.TiFlash.Name()), 118 Blocks: []ast.HintBlock{{DBName: tbl.DBName, BlockName: getBlockName(tbl.Block.Name, tbl.BlockAsName)}}, 119 }) 120 } 121 case *PhysicalIndexLookUpReader: 122 index := pp.IndexCausets[0].(*PhysicalIndexScan) 123 res = append(res, &ast.BlockOptimizerHint{ 124 QBName: utilhint.GenerateQBName(nodeType, pp.blockOffset), 125 HintName: perceptron.NewCIStr(HintUseIndex), 126 Blocks: []ast.HintBlock{{DBName: index.DBName, BlockName: getBlockName(index.Block.Name, index.BlockAsName)}}, 127 Indexes: []perceptron.CIStr{index.Index.Name}, 128 }) 129 case *PhysicalIndexReader: 130 index := pp.IndexCausets[0].(*PhysicalIndexScan) 131 res = append(res, &ast.BlockOptimizerHint{ 132 QBName: utilhint.GenerateQBName(nodeType, pp.blockOffset), 133 HintName: perceptron.NewCIStr(HintUseIndex), 134 Blocks: []ast.HintBlock{{DBName: index.DBName, BlockName: getBlockName(index.Block.Name, index.BlockAsName)}}, 135 Indexes: []perceptron.CIStr{index.Index.Name}, 136 }) 137 case *PhysicalIndexMergeReader: 138 Indexs := make([]perceptron.CIStr, 0, 2) 139 var blockName perceptron.CIStr 140 var blockAsName *perceptron.CIStr 141 for _, partialCauset := range pp.PartialCausets { 142 if index, ok := partialCauset[0].(*PhysicalIndexScan); ok { 143 Indexs = append(Indexs, index.Index.Name) 144 blockName = index.Block.Name 145 blockAsName = index.BlockAsName 146 } else { 147 indexName := perceptron.NewCIStr("PRIMARY") 148 Indexs = append(Indexs, indexName) 149 } 150 } 151 res = append(res, &ast.BlockOptimizerHint{ 152 QBName: utilhint.GenerateQBName(nodeType, pp.blockOffset), 153 HintName: perceptron.NewCIStr(HintIndexMerge), 154 Blocks: []ast.HintBlock{{BlockName: getBlockName(blockName, blockAsName)}}, 155 Indexes: Indexs, 156 }) 157 case *PhysicalHashAgg: 158 res = append(res, &ast.BlockOptimizerHint{ 159 QBName: utilhint.GenerateQBName(nodeType, pp.blockOffset), 160 HintName: perceptron.NewCIStr(HintHashAgg), 161 }) 162 case *PhysicalStreamAgg: 163 res = append(res, &ast.BlockOptimizerHint{ 164 QBName: utilhint.GenerateQBName(nodeType, pp.blockOffset), 165 HintName: perceptron.NewCIStr(HintStreamAgg), 166 }) 167 case *PhysicalMergeJoin: 168 res = append(res, getJoinHints(p.SCtx(), HintSMJ, p.SelectBlockOffset(), nodeType, pp.children...)...) 169 case *PhysicalBroadCastJoin: 170 res = append(res, getJoinHints(p.SCtx(), HintBCJ, p.SelectBlockOffset(), nodeType, pp.children...)...) 171 case *PhysicalHashJoin: 172 res = append(res, getJoinHints(p.SCtx(), HintHJ, p.SelectBlockOffset(), nodeType, pp.children...)...) 173 case *PhysicalIndexJoin: 174 res = append(res, getJoinHints(p.SCtx(), HintINLJ, p.SelectBlockOffset(), nodeType, pp.children[pp.InnerChildIdx])...) 175 case *PhysicalIndexMergeJoin: 176 res = append(res, getJoinHints(p.SCtx(), HintINLMJ, p.SelectBlockOffset(), nodeType, pp.children[pp.InnerChildIdx])...) 177 case *PhysicalIndexHashJoin: 178 res = append(res, getJoinHints(p.SCtx(), HintINLHJ, p.SelectBlockOffset(), nodeType, pp.children[pp.InnerChildIdx])...) 179 } 180 return res 181 }