Skip to content

Commit

Permalink
planner: classify logical mem table logic into a separate file for la…
Browse files Browse the repository at this point in the history
…ter pkg move (#54485)

ref #51664, ref #52714
  • Loading branch information
AilinKid authored Jul 9, 2024
1 parent 8c1ce99 commit 49f1427
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 92 deletions.
1 change: 1 addition & 0 deletions pkg/planner/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ go_library(
"logical_limit.go",
"logical_lock.go",
"logical_max_one_row.go",
"logical_mem_table.go",
"logical_partition_union_all.go",
"logical_plan_builder.go",
"logical_plans.go",
Expand Down
3 changes: 1 addition & 2 deletions pkg/planner/core/find_best_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,7 @@ END:
return bestTask, cntPlan, nil
}

// FindBestTask implements the LogicalPlan interface.
func (p *LogicalMemTable) FindBestTask(prop *property.PhysicalProperty, planCounter *base.PlanCounterTp, opt *optimizetrace.PhysicalOptimizeOp) (t base.Task, cntPlan int64, err error) {
func findBestTask4LogicalMemTable(p *LogicalMemTable, prop *property.PhysicalProperty, planCounter *base.PlanCounterTp, opt *optimizetrace.PhysicalOptimizeOp) (t base.Task, cntPlan int64, err error) {
if prop.MPPPartitionTp != property.AnyType {
return base.InvalidTask, 0, nil
}
Expand Down
6 changes: 0 additions & 6 deletions pkg/planner/core/logical_initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ func (p LogicalShowDDLJobs) Init(ctx base.PlanContext) *LogicalShowDDLJobs {
return &p
}

// Init initializes LogicalMemTable.
func (p LogicalMemTable) Init(ctx base.PlanContext, offset int) *LogicalMemTable {
p.BaseLogicalPlan = logicalop.NewBaseLogicalPlan(ctx, plancodec.TypeMemTableScan, &p, offset)
return &p
}

// Init only assigns type and context.
func (p LogicalCTE) Init(ctx base.PlanContext, offset int) *LogicalCTE {
p.BaseLogicalPlan = logicalop.NewBaseLogicalPlan(ctx, plancodec.TypeCTE, &p, offset)
Expand Down
169 changes: 169 additions & 0 deletions pkg/planner/core/logical_mem_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// Copyright 2024 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 (
"github.com/pingcap/tidb/pkg/expression"
"github.com/pingcap/tidb/pkg/infoschema"
"github.com/pingcap/tidb/pkg/parser/model"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/operator/logicalop"
"github.com/pingcap/tidb/pkg/planner/property"
"github.com/pingcap/tidb/pkg/planner/util"
"github.com/pingcap/tidb/pkg/planner/util/optimizetrace"
"github.com/pingcap/tidb/pkg/planner/util/optimizetrace/logicaltrace"
"github.com/pingcap/tidb/pkg/statistics"
"github.com/pingcap/tidb/pkg/util/plancodec"
)

// LogicalMemTable represents a memory table or virtual table
// Some memory tables wants to take the ownership of some predications
// e.g
// SELECT * FROM cluster_log WHERE type='tikv' AND address='192.16.5.32'
// Assume that the table `cluster_log` is a memory table, which is used
// to retrieve logs from remote components. In the above situation we should
// send log search request to the target TiKV (192.16.5.32) directly instead of
// requesting all cluster components log search gRPC interface to retrieve
// log message and filtering them in TiDB node.
type LogicalMemTable struct {
logicalop.LogicalSchemaProducer

Extractor base.MemTablePredicateExtractor
DBName model.CIStr
TableInfo *model.TableInfo
Columns []*model.ColumnInfo
// QueryTimeRange is used to specify the time range for metrics summary tables and inspection tables
// e.g: select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from metrics_summary;
// select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from metrics_summary_by_label;
// select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from inspection_summary;
// select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from inspection_result;
QueryTimeRange util.QueryTimeRange
}

// Init initializes LogicalMemTable.
func (p LogicalMemTable) Init(ctx base.PlanContext, offset int) *LogicalMemTable {
p.BaseLogicalPlan = logicalop.NewBaseLogicalPlan(ctx, plancodec.TypeMemTableScan, &p, offset)
return &p
}

// *************************** start implementation of logicalPlan interface ***************************

// HashCode inherits BaseLogicalPlan.<0th> implementation.

// PredicatePushDown implements base.LogicalPlan.<1st> interface.
func (p *LogicalMemTable) PredicatePushDown(predicates []expression.Expression, _ *optimizetrace.LogicalOptimizeOp) ([]expression.Expression, base.LogicalPlan) {
if p.Extractor != nil {
predicates = p.Extractor.Extract(p.SCtx(), p.Schema(), p.OutputNames(), predicates)
}
return predicates, p.Self()
}

// PruneColumns implements base.LogicalPlan.<2nd> interface.
func (p *LogicalMemTable) PruneColumns(parentUsedCols []*expression.Column, opt *optimizetrace.LogicalOptimizeOp) (base.LogicalPlan, error) {
switch p.TableInfo.Name.O {
case infoschema.TableStatementsSummary,
infoschema.TableStatementsSummaryHistory,
infoschema.TableSlowQuery,
infoschema.ClusterTableStatementsSummary,
infoschema.ClusterTableStatementsSummaryHistory,
infoschema.ClusterTableSlowLog,
infoschema.TableTiDBTrx,
infoschema.ClusterTableTiDBTrx,
infoschema.TableDataLockWaits,
infoschema.TableDeadlocks,
infoschema.ClusterTableDeadlocks,
infoschema.TableTables:
default:
return p, nil
}
prunedColumns := make([]*expression.Column, 0)
used := expression.GetUsedList(p.SCtx().GetExprCtx().GetEvalCtx(), parentUsedCols, p.Schema())
for i := len(used) - 1; i >= 0; i-- {
if !used[i] && p.Schema().Len() > 1 {
prunedColumns = append(prunedColumns, p.Schema().Columns[i])
p.Schema().Columns = append(p.Schema().Columns[:i], p.Schema().Columns[i+1:]...)
p.SetOutputNames(append(p.OutputNames()[:i], p.OutputNames()[i+1:]...))
p.Columns = append(p.Columns[:i], p.Columns[i+1:]...)
}
}
logicaltrace.AppendColumnPruneTraceStep(p, prunedColumns, opt)
return p, nil
}

// FindBestTask implements the base.LogicalPlan.<3rd> interface.
func (p *LogicalMemTable) FindBestTask(prop *property.PhysicalProperty, planCounter *base.PlanCounterTp, opt *optimizetrace.PhysicalOptimizeOp) (t base.Task, cntPlan int64, err error) {
return findBestTask4LogicalMemTable(p, prop, planCounter, opt)
}

// BuildKeyInfo inherits BaseLogicalPlan.<4th> implementation.

// PushDownTopN inherits BaseLogicalPlan.<5th> implementation.

// DeriveTopN inherits BaseLogicalPlan.<6th> implementation.

// PredicateSimplification inherits BaseLogicalPlan.<7th> implementation.

// ConstantPropagation inherits BaseLogicalPlan.<8th> implementation.

// PullUpConstantPredicates inherits BaseLogicalPlan.<9th> implementation.

// RecursiveDeriveStats inherits BaseLogicalPlan.<10th> implementation.

// DeriveStats implements base.LogicalPlan.<11th> interface.
func (p *LogicalMemTable) DeriveStats(_ []*property.StatsInfo, selfSchema *expression.Schema, _ []*expression.Schema, _ [][]*expression.Column) (*property.StatsInfo, error) {
if p.StatsInfo() != nil {
return p.StatsInfo(), nil
}
statsTable := statistics.PseudoTable(p.TableInfo, false, false)
stats := &property.StatsInfo{
RowCount: float64(statsTable.RealtimeCount),
ColNDVs: make(map[int64]float64, len(p.TableInfo.Columns)),
HistColl: statsTable.GenerateHistCollFromColumnInfo(p.TableInfo, p.Schema().Columns),
StatsVersion: statistics.PseudoVersion,
}
for _, col := range selfSchema.Columns {
stats.ColNDVs[col.UniqueID] = float64(statsTable.RealtimeCount)
}
p.SetStats(stats)
return p.StatsInfo(), nil
}

// ExtractColGroups inherits BaseLogicalPlan.LogicalPlan.<12th> implementation.

// PreparePossibleProperties inherits BaseLogicalPlan.LogicalPlan.<13th> implementation.

// ExhaustPhysicalPlans inherits BaseLogicalPlan.LogicalPlan.<14th> implementation.

// ExtractCorrelatedCols inherits BaseLogicalPlan.LogicalPlan.<15th> implementation.

// MaxOneRow inherits BaseLogicalPlan.LogicalPlan.<16th> implementation.

// Children inherits BaseLogicalPlan.LogicalPlan.<17th> implementation.

// SetChildren inherits BaseLogicalPlan.LogicalPlan.<18th> implementation.

// SetChild inherits BaseLogicalPlan.LogicalPlan.<19th> implementation.

// RollBackTaskMap inherits BaseLogicalPlan.LogicalPlan.<20th> implementation.

// CanPushToCop inherits BaseLogicalPlan.LogicalPlan.<21st> implementation.

// ExtractFD inherits BaseLogicalPlan.LogicalPlan.<22nd> implementation.

// GetBaseLogicalPlan inherits BaseLogicalPlan.LogicalPlan.<23rd> implementation.

// ConvertOuterToInnerJoin inherits BaseLogicalPlan.LogicalPlan.<24th> implementation.

// *************************** end implementation of logicalPlan interface ***************************
24 changes: 0 additions & 24 deletions pkg/planner/core/logical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,30 +156,6 @@ func extractEquivalenceCols(conditions []expression.Expression, sctx base.PlanCo
return equivUniqueIDs
}

// LogicalMemTable represents a memory table or virtual table
// Some memory tables wants to take the ownership of some predications
// e.g
// SELECT * FROM cluster_log WHERE type='tikv' AND address='192.16.5.32'
// Assume that the table `cluster_log` is a memory table, which is used
// to retrieve logs from remote components. In the above situation we should
// send log search request to the target TiKV (192.16.5.32) directly instead of
// requesting all cluster components log search gRPC interface to retrieve
// log message and filtering them in TiDB node.
type LogicalMemTable struct {
logicalop.LogicalSchemaProducer

Extractor base.MemTablePredicateExtractor
DBName model.CIStr
TableInfo *model.TableInfo
Columns []*model.ColumnInfo
// QueryTimeRange is used to specify the time range for metrics summary tables and inspection tables
// e.g: select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from metrics_summary;
// select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from metrics_summary_by_label;
// select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from inspection_summary;
// select /*+ time_range('2020-02-02 12:10:00', '2020-02-02 13:00:00') */ from inspection_result;
QueryTimeRange util.QueryTimeRange
}

// WindowFrame represents a window function frame.
type WindowFrame struct {
Type ast.FrameType
Expand Down
33 changes: 0 additions & 33 deletions pkg/planner/core/rule_column_pruning.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"slices"

"github.com/pingcap/tidb/pkg/expression"
"github.com/pingcap/tidb/pkg/infoschema"
"github.com/pingcap/tidb/pkg/parser/model"
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/planner/core/base"
Expand Down Expand Up @@ -168,38 +167,6 @@ func (ds *DataSource) PruneColumns(parentUsedCols []*expression.Column, opt *opt
return ds, nil
}

// PruneColumns implements base.LogicalPlan interface.
func (p *LogicalMemTable) PruneColumns(parentUsedCols []*expression.Column, opt *optimizetrace.LogicalOptimizeOp) (base.LogicalPlan, error) {
switch p.TableInfo.Name.O {
case infoschema.TableStatementsSummary,
infoschema.TableStatementsSummaryHistory,
infoschema.TableSlowQuery,
infoschema.ClusterTableStatementsSummary,
infoschema.ClusterTableStatementsSummaryHistory,
infoschema.ClusterTableSlowLog,
infoschema.TableTiDBTrx,
infoschema.ClusterTableTiDBTrx,
infoschema.TableDataLockWaits,
infoschema.TableDeadlocks,
infoschema.ClusterTableDeadlocks,
infoschema.TableTables:
default:
return p, nil
}
prunedColumns := make([]*expression.Column, 0)
used := expression.GetUsedList(p.SCtx().GetExprCtx().GetEvalCtx(), parentUsedCols, p.Schema())
for i := len(used) - 1; i >= 0; i-- {
if !used[i] && p.Schema().Len() > 1 {
prunedColumns = append(prunedColumns, p.Schema().Columns[i])
p.Schema().Columns = append(p.Schema().Columns[:i], p.Schema().Columns[i+1:]...)
p.SetOutputNames(append(p.OutputNames()[:i], p.OutputNames()[i+1:]...))
p.Columns = append(p.Columns[:i], p.Columns[i+1:]...)
}
}
logicaltrace.AppendColumnPruneTraceStep(p, prunedColumns, opt)
return p, nil
}

func (p *LogicalJoin) extractUsedCols(parentUsedCols []*expression.Column) (leftCols []*expression.Column, rightCols []*expression.Column) {
for _, eqCond := range p.EqualConditions {
parentUsedCols = append(parentUsedCols, expression.ExtractColumns(eqCond)...)
Expand Down
8 changes: 0 additions & 8 deletions pkg/planner/core/rule_predicate_push_down.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,14 +476,6 @@ func (p *LogicalJoin) outerJoinPropConst(predicates []expression.Expression) []e
return predicates
}

// PredicatePushDown implements base.LogicalPlan PredicatePushDown interface.
func (p *LogicalMemTable) PredicatePushDown(predicates []expression.Expression, _ *optimizetrace.LogicalOptimizeOp) ([]expression.Expression, base.LogicalPlan) {
if p.Extractor != nil {
predicates = p.Extractor.Extract(p.SCtx(), p.Schema(), p.OutputNames(), predicates)
}
return predicates, p.Self()
}

func (*ppdSolver) name() string {
return "predicate_push_down"
}
Expand Down
19 changes: 0 additions & 19 deletions pkg/planner/core/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,6 @@ func (p *basePhysicalPlan) StatsCount() float64 {
return p.StatsInfo().RowCount
}

// DeriveStats implement LogicalPlan DeriveStats interface.
func (p *LogicalMemTable) DeriveStats(_ []*property.StatsInfo, selfSchema *expression.Schema, _ []*expression.Schema, _ [][]*expression.Column) (*property.StatsInfo, error) {
if p.StatsInfo() != nil {
return p.StatsInfo(), nil
}
statsTable := statistics.PseudoTable(p.TableInfo, false, false)
stats := &property.StatsInfo{
RowCount: float64(statsTable.RealtimeCount),
ColNDVs: make(map[int64]float64, len(p.TableInfo.Columns)),
HistColl: statsTable.GenerateHistCollFromColumnInfo(p.TableInfo, p.Schema().Columns),
StatsVersion: statistics.PseudoVersion,
}
for _, col := range selfSchema.Columns {
stats.ColNDVs[col.UniqueID] = float64(statsTable.RealtimeCount)
}
p.SetStats(stats)
return p.StatsInfo(), nil
}

func getFakeStats(schema *expression.Schema) *property.StatsInfo {
profile := &property.StatsInfo{
RowCount: 1,
Expand Down

0 comments on commit 49f1427

Please sign in to comment.