* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
115 lines
3 KiB
Go
115 lines
3 KiB
Go
// Copyright 2015 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,
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
|
||
package plan
|
||
|
||
import (
|
||
"github.com/pingcap/tidb/ast"
|
||
"github.com/pingcap/tidb/parser/opcode"
|
||
)
|
||
|
||
const (
|
||
rateFull float64 = 1
|
||
rateEqual float64 = 0.01
|
||
rateNotEqual float64 = 0.99
|
||
rateBetween float64 = 0.1
|
||
rateGreaterOrLess float64 = 0.33
|
||
rateIsFalse float64 = 0.1
|
||
rateIsNull float64 = 0.1
|
||
rateLike float64 = 0.1
|
||
)
|
||
|
||
// guesstimateFilterRate guesstimates the filter rate for an expression.
|
||
// For example: a table has 100 rows, after filter expression 'a between 0 and 9',
|
||
// 10 rows returned, then the filter rate is '0.1'.
|
||
// It only depends on the expression type, not the expression value.
|
||
// The expr parameter should contain only one column name.
|
||
func guesstimateFilterRate(expr ast.ExprNode) float64 {
|
||
switch x := expr.(type) {
|
||
case *ast.BetweenExpr:
|
||
return rateBetween
|
||
case *ast.BinaryOperationExpr:
|
||
return guesstimateBinop(x)
|
||
case *ast.ColumnNameExpr:
|
||
return rateFull
|
||
case *ast.IsNullExpr:
|
||
return guesstimateIsNull(x)
|
||
case *ast.IsTruthExpr:
|
||
return guesstimateIsTrue(x)
|
||
case *ast.ParenthesesExpr:
|
||
return guesstimateFilterRate(x.Expr)
|
||
case *ast.PatternInExpr:
|
||
return guesstimatePatternIn(x)
|
||
case *ast.PatternLikeExpr:
|
||
return guesstimatePatternLike(x)
|
||
}
|
||
return rateFull
|
||
}
|
||
|
||
func guesstimateBinop(expr *ast.BinaryOperationExpr) float64 {
|
||
switch expr.Op {
|
||
case opcode.AndAnd:
|
||
// P(A and B) = P(A) * P(B)
|
||
return guesstimateFilterRate(expr.L) * guesstimateFilterRate(expr.R)
|
||
case opcode.OrOr:
|
||
// P(A or B) = P(A) + P(B) – P(A and B)
|
||
rateL := guesstimateFilterRate(expr.L)
|
||
rateR := guesstimateFilterRate(expr.R)
|
||
return rateL + rateR - rateL*rateR
|
||
case opcode.EQ:
|
||
return rateEqual
|
||
case opcode.GT, opcode.GE, opcode.LT, opcode.LE:
|
||
return rateGreaterOrLess
|
||
case opcode.NE:
|
||
return rateNotEqual
|
||
}
|
||
return rateFull
|
||
}
|
||
|
||
func guesstimateIsNull(expr *ast.IsNullExpr) float64 {
|
||
if expr.Not {
|
||
return rateFull - rateIsNull
|
||
}
|
||
return rateIsNull
|
||
}
|
||
|
||
func guesstimateIsTrue(expr *ast.IsTruthExpr) float64 {
|
||
if expr.True == 0 {
|
||
if expr.Not {
|
||
return rateFull - rateIsFalse
|
||
}
|
||
return rateIsFalse
|
||
}
|
||
if expr.Not {
|
||
return rateIsFalse + rateIsNull
|
||
}
|
||
return rateFull - rateIsFalse - rateIsNull
|
||
}
|
||
|
||
func guesstimatePatternIn(expr *ast.PatternInExpr) float64 {
|
||
if len(expr.List) > 0 {
|
||
rate := rateEqual * float64(len(expr.List))
|
||
if expr.Not {
|
||
return rateFull - rate
|
||
}
|
||
return rate
|
||
}
|
||
return rateFull
|
||
}
|
||
|
||
func guesstimatePatternLike(expr *ast.PatternLikeExpr) float64 {
|
||
if expr.Not {
|
||
return rateFull - rateLike
|
||
}
|
||
return rateLike
|
||
}
|