Repository: matrixorigin/matrixone
Pull request #7329 (2022-12-27 01:13:16)

[Enhancement]: optimize filter expr for zonemap #7328
## What type of PR is this?

- [ ] API-change
- [ ] BUG
- [x] Improvement
- [ ] Documentation
- [ ] Feature
- [ ] Test and CI
- [ ] Code Refactoring

## Which issue(s) this PR fixes:

issue #7328

## What this PR does / why we need it:


Patch:
diff --git a/pkg/sql/plan/utils.go b/pkg/sql/plan/utils.go
index e8920baee..d4618720c 100644
--- a/pkg/sql/plan/utils.go
+++ b/pkg/sql/plan/utils.go
@@ -792,11 +792,38 @@ func containsParamRef(expr *plan.Expr) bool {
 	return ret
 }
 
+func CheckExprIsMonotonic(ctx context.Context, expr *plan.Expr) bool {
+	if expr == nil {
+		return false
+	}
+	switch exprImpl := expr.Expr.(type) {
+	case *plan.Expr_F:
+		for _, arg := range exprImpl.F.Args {
+			isMonotonic := CheckExprIsMonotonic(ctx, arg)
+			if !isMonotonic {
+				return false
+			}
+		}
+
+		isMonotonic, _ := function.GetFunctionIsMonotonicById(ctx, exprImpl.F.Func.GetObj())
+		if !isMonotonic {
+			return false
+		}
+
+		return true
+	default:
+		return true
+	}
+}
+
 // handle the filter list for zonemap. rewrite and constFold
 func HandleFiltersForZM(exprList []*plan.Expr, proc *process.Process) *plan.Expr {
+	if proc == nil || proc.Ctx == nil {
+		return nil
+	}
 	var newExprList []*plan.Expr
 	for _, expr := range exprList {
-		if !containsParamRef(expr) {
+		if !containsParamRef(expr) && CheckExprIsMonotonic(proc.Ctx, expr) {
 			newExprList = append(newExprList, expr)
 		}
 	}
diff --git a/pkg/vm/engine/disttae/table.go b/pkg/vm/engine/disttae/table.go
index 02bba6311..9d21abf72 100644
--- a/pkg/vm/engine/disttae/table.go
+++ b/pkg/vm/engine/disttae/table.go
@@ -16,6 +16,7 @@ package disttae
 
 import (
 	"context"
+	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
 	"math/rand"
 
 	"github.com/google/uuid"
@@ -46,7 +47,7 @@ func (tbl *table) FilteredStats(ctx context.Context, expr *plan.Expr) (int32, in
 	var blockNum, totalBlockCnt int
 	var outcnt int64
 
-	exprMono := checkExprIsMonotonic(ctx, expr)
+	exprMono := plan2.CheckExprIsMonotonic(ctx, expr)
 	columnMap, columns, maxCol := getColumnsByExpr(expr, tbl.getTableDef())
 
 	for _, blockmetas := range tbl.meta.blocks {
@@ -207,7 +208,7 @@ func (tbl *table) Ranges(ctx context.Context, expr *plan.Expr) ([][]byte, error)
 	}
 	tbl.meta.modifedBlocks = make([][]ModifyBlockMeta, len(tbl.meta.blocks))
 
-	exprMono := checkExprIsMonotonic(tbl.db.txn.proc.Ctx, expr)
+	exprMono := plan2.CheckExprIsMonotonic(tbl.db.txn.proc.Ctx, expr)
 	columnMap, columns, maxCol := getColumnsByExpr(expr, tbl.getTableDef())
 	for _, i := range dnList {
 		blks, deletes := tbl.parts[i].BlockList(ctx, tbl.db.txn.meta.SnapshotTS,
diff --git a/pkg/vm/engine/disttae/tools.go b/pkg/vm/engine/disttae/tools.go
index f81577cd1..5c4bbec9c 100644
--- a/pkg/vm/engine/disttae/tools.go
+++ b/pkg/vm/engine/disttae/tools.go
@@ -1071,7 +1071,7 @@ func genModifedBlocks(ctx context.Context, deletes map[uint64][]int, orgs, modfs
 		blockMap[modfs[i].Info.BlockID] = true
 	}
 
-	exprMono := checkExprIsMonotonic(ctx, expr)
+	exprMono := plantool.CheckExprIsMonotonic(ctx, expr)
 	columnMap, columns, maxCol := getColumnsByExpr(expr, tableDef)
 	for i, blk := range orgs {
 		if !inBlockMap(blk, blockMap) {
diff --git a/pkg/vm/engine/disttae/util.go b/pkg/vm/engine/disttae/util.go
index 6105305e7..78748a8d3 100644
--- a/pkg/vm/engine/disttae/util.go
+++ b/pkg/vm/engine/disttae/util.go
@@ -46,30 +46,6 @@ const (
 	MAX_RANGE_SIZE int64  = 200
 )
 
-func checkExprIsMonotonic(ctx context.Context, expr *plan.Expr) bool {
-	if expr == nil {
-		return false
-	}
-	switch exprImpl := expr.Expr.(type) {
-	case *plan.Expr_F:
-		for _, arg := range exprImpl.F.Args {
-			isMonotonic := checkExprIsMonotonic(ctx, arg)
-			if !isMonotonic {
-				return false
-			}
-		}
-
-		isMonotonic, _ := function.GetFunctionIsMonotonicById(ctx, exprImpl.F.Func.GetObj())
-		if !isMonotonic {
-			return false
-		}
-
-		return true
-	default:
-		return true
-	}
-}
-
 func getColumnMapByExpr(expr *plan.Expr, tableDef *plan.TableDef, columnMap *map[int]int) {
 	if expr == nil {
 		return


Test patch:
diff --git a/pkg/vm/engine/disttae/util_test.go b/pkg/vm/engine/disttae/util_test.go
index 10933c57e..ae8636ca3 100644
--- a/pkg/vm/engine/disttae/util_test.go
+++ b/pkg/vm/engine/disttae/util_test.go
@@ -168,7 +168,7 @@ func TestCheckExprIsMonotonic(t *testing.T) {
 
 	t.Run("test checkExprIsMonotonic", func(t *testing.T) {
 		for i, testCase := range testCases {
-			isMonotonic := checkExprIsMonotonic(context.TODO(), testCase.expr)
+			isMonotonic := plan2.CheckExprIsMonotonic(context.TODO(), testCase.expr)
 			if isMonotonic != testCase.result {
 				t.Fatalf("checkExprIsMonotonic testExprs[%d] is different with expected", i)
 			}