tidb plan_cost_detail 源码

  • 2022-09-19
  • 浏览 (423)

tidb plan_cost_detail 代码

文件路径:/planner/core/plan_cost_detail.go

// Copyright 2022 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package core

import (
	"fmt"

	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/util/tracing"
)

const (
	// RowCountLbl indicates for rowCount
	RowCountLbl = "rowCount"
	// RowSizeLbl indicates rowSize
	RowSizeLbl = "rowSize"
	// BuildRowCountLbl indicates rowCount on build side
	BuildRowCountLbl = "buildRowCount"
	// ProbeRowCountLbl indicates rowCount on probe side
	ProbeRowCountLbl = "probeRowCount"
	// NumPairsLbl indicates numPairs
	NumPairsLbl = "numPairs"

	// NetworkFactorLbl indicates networkFactor
	NetworkFactorLbl = "networkFactor"
	// SeekFactorLbl indicates seekFactor
	SeekFactorLbl = "seekFactor"
	// ScanFactorLbl indicates for scanFactor
	ScanFactorLbl = "scanFactor"
	// SelectionFactorLbl indicates selection factor
	SelectionFactorLbl = "selectionFactor"
	// CPUFactorLbl indicates cpu factor
	CPUFactorLbl = "cpuFactor"
	// MemoryFactorLbl indicates mem factor
	MemoryFactorLbl = "memoryFactor"
	// DiskFactorLbl indicates disk factor
	DiskFactorLbl = "diskFactor"
	// ConcurrencyFactorLbl indicates for concurrency factor
	ConcurrencyFactorLbl = "concurrencyFactor"

	// ScanConcurrencyLbl indicates sql scan concurrency
	ScanConcurrencyLbl = "scanConcurrency"
	// HashJoinConcurrencyLbl indicates concurrency for hash join
	HashJoinConcurrencyLbl = "hashJoinConcurrency"

	// NetSeekCostLbl indicates netSeek cost
	NetSeekCostLbl = "netSeekCost"
	// TablePlanCostLbl indicates tablePlan cost
	TablePlanCostLbl = "tablePlanCost"
	// IndexPlanCostLbl indicates indexPlan cost
	IndexPlanCostLbl = "indexPlanCost"

	// ProbeCostDetailLbl indicates probeCost
	ProbeCostDetailLbl = "probeCostDetail"
	// ProbeCostDescLbl indicates description for probe cost
	ProbeCostDescLbl = "probeCostDesc"
	// CPUCostDetailLbl indicates cpuCost detail
	CPUCostDetailLbl = "cpuCostDetail"
	// CPUCostDescLbl indicates description for cpu cost
	CPUCostDescLbl = "cpuCostDesc"
	// MemCostDetailLbl indicates mem cost detail
	MemCostDetailLbl = "memCostDetail"
	// MemCostDescLbl indicates description for mem cost
	MemCostDescLbl = "memCostDesc"
	// DiskCostDetailLbl indicates disk cost detail
	DiskCostDetailLbl = "diskCostDetail"
	// DiskCostDescLbl indicates description for disk cost
	DiskCostDescLbl = "diskCostDesc"
	// ProbeDiskCostLbl indicates probe disk cost detail
	ProbeDiskCostLbl = "probeDiskCostDetail"
	// ProbeDiskCostDescLbl indicates description for probe disk cost
	ProbeDiskCostDescLbl = "probeDiskCostDesc"

	// MemQuotaLbl indicates memory quota
	MemQuotaLbl = "memQuota"
)

func setPointGetPlanCostDetail(p *PointGetPlan, opt *physicalOptimizeOp,
	rowSize, networkFactor, seekFactor float64) {
	if opt == nil {
		return
	}
	detail := tracing.NewPhysicalPlanCostDetail(p.ID(), p.TP())
	detail.AddParam(RowSizeLbl, rowSize).
		AddParam(NetworkFactorLbl, networkFactor).
		AddParam(SeekFactorLbl, seekFactor).
		SetDesc(fmt.Sprintf("%s*%s+%s", RowSizeLbl, NetworkFactorLbl, SeekFactorLbl))
	opt.appendPlanCostDetail(detail)
}

func setBatchPointGetPlanCostDetail(p *BatchPointGetPlan, opt *physicalOptimizeOp,
	rowCount, rowSize, networkFactor, seekFactor float64, scanConcurrency int) {
	if opt == nil {
		return
	}
	detail := tracing.NewPhysicalPlanCostDetail(p.ID(), p.TP())
	detail.AddParam(RowCountLbl, rowCount).
		AddParam(RowSizeLbl, rowSize).
		AddParam(NetworkFactorLbl, networkFactor).
		AddParam(SeekFactorLbl, seekFactor).
		AddParam(ScanConcurrencyLbl, scanConcurrency).
		SetDesc(fmt.Sprintf("(%s*%s*%s+%s*%s)/%s",
			RowCountLbl, RowSizeLbl, NetworkFactorLbl, RowCountLbl, SeekFactorLbl, ScanConcurrencyLbl))
	opt.appendPlanCostDetail(detail)
}

func setPhysicalTableOrIndexScanCostDetail(p PhysicalPlan, opt *physicalOptimizeOp,
	rowCount, rowSize, scanFactor float64, costModelVersion int) {
	if opt == nil {
		return
	}
	_, ok1 := p.(*PhysicalTableScan)
	_, ok2 := p.(*PhysicalIndexScan)
	if !ok1 && !ok2 {
		return
	}
	detail := tracing.NewPhysicalPlanCostDetail(p.ID(), p.TP())
	detail.AddParam(RowCountLbl, rowCount).
		AddParam(RowSizeLbl, rowSize).
		AddParam(ScanFactorLbl, scanFactor)
	var desc string
	if costModelVersion == modelVer1 {
		desc = fmt.Sprintf("%s*%s*%s", RowCountLbl, RowSizeLbl, ScanFactorLbl)
	} else {
		desc = fmt.Sprintf("%s*log2(%s)*%s", RowCountLbl, RowSizeLbl, ScanFactorLbl)
	}
	detail.SetDesc(desc)
	opt.appendPlanCostDetail(detail)
}

func setPhysicalTableReaderCostDetail(p *PhysicalTableReader, opt *physicalOptimizeOp,
	rowCount, rowSize, networkFactor, netSeekCost, tablePlanCost float64,
	scanConcurrency int, storeType kv.StoreType) {
	// tracer haven't support non tikv plan for now
	if opt == nil || storeType != kv.TiKV {
		return
	}
	detail := tracing.NewPhysicalPlanCostDetail(p.ID(), p.TP())
	detail.AddParam(RowCountLbl, rowCount).
		AddParam(RowSizeLbl, rowSize).
		AddParam(NetworkFactorLbl, networkFactor).
		AddParam(NetSeekCostLbl, netSeekCost).
		AddParam(TablePlanCostLbl, tablePlanCost).
		AddParam(ScanConcurrencyLbl, scanConcurrency)
	detail.SetDesc(fmt.Sprintf("(%s+%s*%s*%s+%s)/%s", TablePlanCostLbl,
		RowCountLbl, RowSizeLbl, NetworkFactorLbl, NetSeekCostLbl, ScanConcurrencyLbl))
	opt.appendPlanCostDetail(detail)
}

func setPhysicalIndexReaderCostDetail(p *PhysicalIndexReader, opt *physicalOptimizeOp,
	rowCount, rowSize, networkFactor, netSeekCost, indexPlanCost float64,
	scanConcurrency int) {
	if opt == nil {
		return
	}
	detail := tracing.NewPhysicalPlanCostDetail(p.ID(), p.TP())
	detail.AddParam(RowCountLbl, rowCount).
		AddParam(RowSizeLbl, rowSize).
		AddParam(NetworkFactorLbl, networkFactor).
		AddParam(NetSeekCostLbl, netSeekCost).
		AddParam(IndexPlanCostLbl, indexPlanCost).
		AddParam(ScanConcurrencyLbl, scanConcurrency)
	detail.SetDesc(fmt.Sprintf("(%s+%s*%s*%s+%s)/%s", IndexPlanCostLbl,
		RowCountLbl, RowSizeLbl, NetworkFactorLbl, NetSeekCostLbl, ScanConcurrencyLbl))
	opt.appendPlanCostDetail(detail)
}

func setPhysicalHashJoinCostDetail(p *PhysicalHashJoin, opt *physicalOptimizeOp, spill bool,
	buildCnt, probeCnt, cpuFactor, rowSize, numPairs,
	cpuCost, probeCPUCost, memCost, diskCost, probeDiskCost,
	diskFactor, memoryFactor, concurrencyFactor float64,
	memQuota int64) {
	if opt == nil {
		return
	}
	detail := tracing.NewPhysicalPlanCostDetail(p.ID(), p.TP())
	diskCostDetail := &HashJoinDiskCostDetail{
		Spill:           spill,
		UseOuterToBuild: p.UseOuterToBuild,
		BuildRowCount:   buildCnt,
		DiskFactor:      diskFactor,
		RowSize:         rowSize,
		ProbeDiskCost: &HashJoinProbeDiskCostDetail{
			SelectionFactor: SelectionFactor,
			NumPairs:        numPairs,
			HasConditions:   len(p.LeftConditions)+len(p.RightConditions) > 0,
			Cost:            probeDiskCost,
		},
		Cost: diskCost,
	}
	memoryCostDetail := &HashJoinMemoryCostDetail{
		Spill:         spill,
		MemQuota:      memQuota,
		RowSize:       rowSize,
		BuildRowCount: buildCnt,
		MemoryFactor:  memoryFactor,
		Cost:          memCost,
	}
	cpuCostDetail := &HashJoinCPUCostDetail{
		BuildRowCount:     buildCnt,
		CPUFactor:         cpuFactor,
		ConcurrencyFactor: concurrencyFactor,
		ProbeCost: &HashJoinProbeCostDetail{
			NumPairs:        numPairs,
			HasConditions:   len(p.LeftConditions)+len(p.RightConditions) > 0,
			SelectionFactor: SelectionFactor,
			ProbeRowCount:   probeCnt,
			Cost:            probeCPUCost,
		},
		HashJoinConcurrency: p.Concurrency,
		Spill:               spill,
		Cost:                cpuCost,
		UseOuterToBuild:     p.UseOuterToBuild,
	}

	// record cpu cost detail
	detail.AddParam(CPUCostDetailLbl, cpuCostDetail).
		AddParam(CPUCostDescLbl, cpuCostDetail.desc()).
		AddParam(ProbeCostDescLbl, cpuCostDetail.probeCostDesc())
	// record memory cost detail
	detail.AddParam(MemCostDetailLbl, memoryCostDetail).
		AddParam(MemCostDescLbl, memoryCostDetail.desc())
	// record disk cost detail
	detail.AddParam(DiskCostDetailLbl, diskCostDetail).
		AddParam(DiskCostDescLbl, diskCostDetail.desc()).
		AddParam(ProbeDiskCostDescLbl, diskCostDetail.probeDesc())

	detail.SetDesc(fmt.Sprintf("%s+%s+%s+all children cost", CPUCostDetailLbl, MemCostDetailLbl, DiskCostDetailLbl))
	opt.appendPlanCostDetail(detail)
}

// HashJoinProbeCostDetail indicates probe cpu cost detail
type HashJoinProbeCostDetail struct {
	NumPairs        float64 `json:"numPairs"`
	HasConditions   bool    `json:"hasConditions"`
	SelectionFactor float64 `json:"selectionFactor"`
	ProbeRowCount   float64 `json:"probeRowCount"`
	Cost            float64 `json:"cost"`
}

// HashJoinCPUCostDetail indicates cpu cost detail
type HashJoinCPUCostDetail struct {
	BuildRowCount       float64                  `json:"buildRowCount"`
	CPUFactor           float64                  `json:"cpuFactor"`
	ConcurrencyFactor   float64                  `json:"concurrencyFactor"`
	ProbeCost           *HashJoinProbeCostDetail `json:"probeCost"`
	HashJoinConcurrency uint                     `json:"hashJoinConcurrency"`
	Spill               bool                     `json:"spill"`
	Cost                float64                  `json:"cost"`
	UseOuterToBuild     bool                     `json:"useOuterToBuild"`
}

func (h *HashJoinCPUCostDetail) desc() string {
	var cpuCostDesc string
	buildCostDesc := fmt.Sprintf("%s*%s", BuildRowCountLbl, CPUFactorLbl)
	cpuCostDesc = fmt.Sprintf("%s+%s+(%s+1)*%s)", buildCostDesc, ProbeCostDetailLbl, HashJoinConcurrencyLbl, ConcurrencyFactorLbl)
	if h.UseOuterToBuild {
		if h.Spill {
			cpuCostDesc = fmt.Sprintf("%s+%s", cpuCostDesc, buildCostDesc)
		} else {
			cpuCostDesc = fmt.Sprintf("%s+%s/%s", cpuCostDesc, buildCostDesc, HashJoinConcurrencyLbl)
		}
	}
	return cpuCostDesc
}

func (h *HashJoinCPUCostDetail) probeCostDesc() string {
	var probeCostDesc string
	if h.ProbeCost.HasConditions {
		probeCostDesc = fmt.Sprintf("(%s*%s*%s+%s*%s)/%s",
			NumPairsLbl, CPUFactorLbl, SelectionFactorLbl,
			ProbeRowCountLbl, CPUFactorLbl, HashJoinConcurrencyLbl)
	} else {
		probeCostDesc = fmt.Sprintf("(%s*%s)/%s",
			NumPairsLbl, CPUFactorLbl,
			HashJoinConcurrencyLbl)
	}
	return probeCostDesc
}

// HashJoinMemoryCostDetail indicates memory cost detail
type HashJoinMemoryCostDetail struct {
	Spill         bool    `json:"spill"`
	MemQuota      int64   `json:"memQuota"`
	RowSize       float64 `json:"rowSize"`
	BuildRowCount float64 `json:"buildRowCount"`
	MemoryFactor  float64 `json:"memoryFactor"`
	Cost          float64 `json:"cost"`
}

func (h *HashJoinMemoryCostDetail) desc() string {
	memCostDesc := fmt.Sprintf("%s*%s", BuildRowCountLbl, MemoryFactorLbl)
	if h.Spill {
		memCostDesc = fmt.Sprintf("%s*%s/(%s*%s)", memCostDesc, MemQuotaLbl, RowSizeLbl, BuildRowCountLbl)
	}
	return memCostDesc
}

// HashJoinProbeDiskCostDetail indicates probe disk cost detail
type HashJoinProbeDiskCostDetail struct {
	SelectionFactor float64 `json:"selectionFactor"`
	NumPairs        float64 `json:"numPairs"`
	HasConditions   bool    `json:"hasConditions"`
	Cost            float64 `json:"cost"`
}

// HashJoinDiskCostDetail indicates disk cost detail
type HashJoinDiskCostDetail struct {
	Spill           bool                         `json:"spill"`
	UseOuterToBuild bool                         `json:"useOuterToBuild"`
	BuildRowCount   float64                      `json:"buildRowCount"`
	DiskFactor      float64                      `json:"diskFactor"`
	RowSize         float64                      `json:"rowSize"`
	ProbeDiskCost   *HashJoinProbeDiskCostDetail `json:"probeDiskCost"`
	Cost            float64                      `json:"cost"`
}

func (h *HashJoinDiskCostDetail) desc() string {
	if !h.Spill {
		return ""
	}
	buildDiskCost := fmt.Sprintf("%s*%s*%s", BuildRowCountLbl, DiskFactorLbl, RowSizeLbl)
	desc := fmt.Sprintf("%s+%s", buildDiskCost, ProbeDiskCostLbl)
	if h.UseOuterToBuild {
		desc = fmt.Sprintf("%s+%s", desc, buildDiskCost)
	}
	return desc
}

func (h *HashJoinDiskCostDetail) probeDesc() string {
	if !h.Spill {
		return ""
	}
	desc := fmt.Sprintf("%s*%s*%s", NumPairsLbl, DiskFactorLbl, RowSizeLbl)
	if h.ProbeDiskCost.HasConditions {
		desc = fmt.Sprintf("%s*%s", desc, SelectionFactorLbl)
	}
	return desc
}

相关信息

tidb 源码目录

相关文章

tidb access_object 源码

tidb collect_column_stats_usage 源码

tidb common_plans 源码

tidb encode 源码

tidb errors 源码

tidb exhaust_physical_plans 源码

tidb explain 源码

tidb expression_rewriter 源码

tidb find_best_task 源码

tidb flat_plan 源码

0  赞