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  }