From 3f0514eb6b3bffb92e792b617705551594254dce Mon Sep 17 00:00:00 2001 From: Hangjie Mo Date: Fri, 25 Oct 2024 14:59:32 +0800 Subject: [PATCH] planner, table: list partition support prune non point range (#56725) close pingcap/tidb#56673 --- .../integration_partition_suite_in.json | 20 ++- .../integration_partition_suite_out.json | 133 ++++++++++++------ pkg/planner/core/logical_plan_trace_test.go | 4 +- pkg/planner/core/rule_partition_processor.go | 40 ++++-- pkg/table/tables/partition.go | 79 +++++++++-- .../partition/integration_partition.result | 12 +- .../planner/core/integration_partition.result | 22 +++ .../t/planner/core/integration_partition.test | 12 ++ 8 files changed, 234 insertions(+), 88 deletions(-) diff --git a/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_in.json b/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_in.json index 7173f107783fc..c45821aa50e67 100644 --- a/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_in.json +++ b/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_in.json @@ -9,15 +9,21 @@ "explain format = 'brief' select * from tcollist where a in (2)", "explain format = 'brief' select * from tcollist where a in (7)", "explain format = 'brief' select * from tcollist where a in (0,5)", - // not in: not support + // not in "explain format = 'brief' select * from tlist where a not in (0, 1, 2, 3, 4, 5, 6, 7, 8)", "explain format = 'brief' select * from tcollist where a not in (0, 1, 2, 3, 4, 5, 6, 7, 8)", - // GE: not support - "explain format = 'brief' select * from tlist where a >= 7", - "explain format = 'brief' select * from tcollist where a >= 7", - // LE: not support - "explain format = 'brief' select * from tlist where a <= 7", - "explain format = 'brief' select * from tcollist where a <= 7", + // GE + "explain format = 'brief' select * from tlist where a >= 8", + "explain format = 'brief' select * from tcollist where a >= 8", + // LE + "explain format = 'brief' select * from tlist where a <= 6", + "explain format = 'brief' select * from tcollist where a <= 6", + // GT + "explain format = 'brief' select * from tlist where a > 8", + "explain format = 'brief' select * from tcollist where a > 8", + // LT + "explain format = 'brief' select * from tlist where a < 6", + "explain format = 'brief' select * from tcollist where a < 6", // or "explain format = 'brief' select * from tlist where a=0 or a=7", "explain format = 'brief' select * from tlist where a=0 or a=1 or a=6 or a=11", diff --git a/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_out.json b/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_out.json index f4fba3dc27975..fbdb4ea477f96 100644 --- a/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_out.json +++ b/pkg/planner/core/casetest/partition/testdata/integration_partition_suite_out.json @@ -91,24 +91,14 @@ { "SQL": "explain format = 'brief' select * from tlist where a not in (0, 1, 2, 3, 4, 5, 6, 7, 8)", "DynamicPlan": [ - "TableReader 3583.33 root partition:all data:Selection", + "TableReader 3583.33 root partition:p3 data:Selection", "└─Selection 3583.33 cop[tikv] not(in(list_partition_pruning.tlist.a, 0, 1, 2, 3, 4, 5, 6, 7, 8))", " └─TableFullScan 10000.00 cop[tikv] table:tlist keep order:false, stats:pseudo" ], "StaticPlan": [ - "PartitionUnion 14333.33 root ", - "├─TableReader 3583.33 root data:Selection", - "│ └─Selection 3583.33 cop[tikv] not(in(list_partition_pruning.tlist.a, 0, 1, 2, 3, 4, 5, 6, 7, 8))", - "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p0 keep order:false, stats:pseudo", - "├─TableReader 3583.33 root data:Selection", - "│ └─Selection 3583.33 cop[tikv] not(in(list_partition_pruning.tlist.a, 0, 1, 2, 3, 4, 5, 6, 7, 8))", - "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p1 keep order:false, stats:pseudo", - "├─TableReader 3583.33 root data:Selection", - "│ └─Selection 3583.33 cop[tikv] not(in(list_partition_pruning.tlist.a, 0, 1, 2, 3, 4, 5, 6, 7, 8))", - "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p2 keep order:false, stats:pseudo", - "└─TableReader 3583.33 root data:Selection", - " └─Selection 3583.33 cop[tikv] not(in(list_partition_pruning.tlist.a, 0, 1, 2, 3, 4, 5, 6, 7, 8))", - " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p3 keep order:false, stats:pseudo" + "TableReader 3583.33 root data:Selection", + "└─Selection 3583.33 cop[tikv] not(in(list_partition_pruning.tlist.a, 0, 1, 2, 3, 4, 5, 6, 7, 8))", + " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p3 keep order:false, stats:pseudo" ] }, { @@ -125,88 +115,139 @@ ] }, { - "SQL": "explain format = 'brief' select * from tlist where a >= 7", + "SQL": "explain format = 'brief' select * from tlist where a >= 8", "DynamicPlan": [ - "TableReader 3333.33 root partition:all data:Selection", - "└─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 7)", + "TableReader 3333.33 root partition:p2,p3 data:Selection", + "└─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 8)", " └─TableFullScan 10000.00 cop[tikv] table:tlist keep order:false, stats:pseudo" ], "StaticPlan": [ - "PartitionUnion 13333.33 root ", - "├─TableReader 3333.33 root data:Selection", - "│ └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 7)", - "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p0 keep order:false, stats:pseudo", - "├─TableReader 3333.33 root data:Selection", - "│ └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 7)", - "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p1 keep order:false, stats:pseudo", + "PartitionUnion 6666.67 root ", "├─TableReader 3333.33 root data:Selection", - "│ └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 7)", + "│ └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 8)", "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p2 keep order:false, stats:pseudo", "└─TableReader 3333.33 root data:Selection", - " └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 7)", + " └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tlist.a, 8)", " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p3 keep order:false, stats:pseudo" ] }, { - "SQL": "explain format = 'brief' select * from tcollist where a >= 7", + "SQL": "explain format = 'brief' select * from tcollist where a >= 8", "DynamicPlan": [ "TableReader 3333.33 root partition:p2,p3 data:Selection", - "└─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tcollist.a, 7)", + "└─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tcollist.a, 8)", " └─TableFullScan 10000.00 cop[tikv] table:tcollist keep order:false, stats:pseudo" ], "StaticPlan": [ "PartitionUnion 6666.67 root ", "├─TableReader 3333.33 root data:Selection", - "│ └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tcollist.a, 7)", + "│ └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tcollist.a, 8)", "│ └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p2 keep order:false, stats:pseudo", "└─TableReader 3333.33 root data:Selection", - " └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tcollist.a, 7)", + " └─Selection 3333.33 cop[tikv] ge(list_partition_pruning.tcollist.a, 8)", " └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p3 keep order:false, stats:pseudo" ] }, { - "SQL": "explain format = 'brief' select * from tlist where a <= 7", + "SQL": "explain format = 'brief' select * from tlist where a <= 6", "DynamicPlan": [ - "TableReader 3323.33 root partition:all data:Selection", - "└─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 7)", + "TableReader 3323.33 root partition:p0,p1,p2 data:Selection", + "└─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 6)", " └─TableFullScan 10000.00 cop[tikv] table:tlist keep order:false, stats:pseudo" ], "StaticPlan": [ - "PartitionUnion 13293.33 root ", + "PartitionUnion 9970.00 root ", "├─TableReader 3323.33 root data:Selection", - "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 7)", + "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 6)", "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p0 keep order:false, stats:pseudo", "├─TableReader 3323.33 root data:Selection", - "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 7)", + "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 6)", "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p1 keep order:false, stats:pseudo", - "├─TableReader 3323.33 root data:Selection", - "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 7)", - "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p2 keep order:false, stats:pseudo", "└─TableReader 3323.33 root data:Selection", - " └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 7)", - " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p3 keep order:false, stats:pseudo" + " └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tlist.a, 6)", + " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p2 keep order:false, stats:pseudo" ] }, { - "SQL": "explain format = 'brief' select * from tcollist where a <= 7", + "SQL": "explain format = 'brief' select * from tcollist where a <= 6", "DynamicPlan": [ "TableReader 3323.33 root partition:p0,p1,p2 data:Selection", - "└─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 7)", + "└─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 6)", " └─TableFullScan 10000.00 cop[tikv] table:tcollist keep order:false, stats:pseudo" ], "StaticPlan": [ "PartitionUnion 9970.00 root ", "├─TableReader 3323.33 root data:Selection", - "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 7)", + "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 6)", "│ └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p0 keep order:false, stats:pseudo", "├─TableReader 3323.33 root data:Selection", - "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 7)", + "│ └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 6)", "│ └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p1 keep order:false, stats:pseudo", "└─TableReader 3323.33 root data:Selection", - " └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 7)", + " └─Selection 3323.33 cop[tikv] le(list_partition_pruning.tcollist.a, 6)", " └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p2 keep order:false, stats:pseudo" ] }, + { + "SQL": "explain format = 'brief' select * from tlist where a > 8", + "DynamicPlan": [ + "TableReader 3333.33 root partition:p3 data:Selection", + "└─Selection 3333.33 cop[tikv] gt(list_partition_pruning.tlist.a, 8)", + " └─TableFullScan 10000.00 cop[tikv] table:tlist keep order:false, stats:pseudo" + ], + "StaticPlan": [ + "TableReader 3333.33 root data:Selection", + "└─Selection 3333.33 cop[tikv] gt(list_partition_pruning.tlist.a, 8)", + " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p3 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from tcollist where a > 8", + "DynamicPlan": [ + "TableReader 3333.33 root partition:p3 data:Selection", + "└─Selection 3333.33 cop[tikv] gt(list_partition_pruning.tcollist.a, 8)", + " └─TableFullScan 10000.00 cop[tikv] table:tcollist keep order:false, stats:pseudo" + ], + "StaticPlan": [ + "TableReader 3333.33 root data:Selection", + "└─Selection 3333.33 cop[tikv] gt(list_partition_pruning.tcollist.a, 8)", + " └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p3 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from tlist where a < 6", + "DynamicPlan": [ + "TableReader 3323.33 root partition:p0,p1 data:Selection", + "└─Selection 3323.33 cop[tikv] lt(list_partition_pruning.tlist.a, 6)", + " └─TableFullScan 10000.00 cop[tikv] table:tlist keep order:false, stats:pseudo" + ], + "StaticPlan": [ + "PartitionUnion 6646.67 root ", + "├─TableReader 3323.33 root data:Selection", + "│ └─Selection 3323.33 cop[tikv] lt(list_partition_pruning.tlist.a, 6)", + "│ └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p0 keep order:false, stats:pseudo", + "└─TableReader 3323.33 root data:Selection", + " └─Selection 3323.33 cop[tikv] lt(list_partition_pruning.tlist.a, 6)", + " └─TableFullScan 10000.00 cop[tikv] table:tlist, partition:p1 keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from tcollist where a < 6", + "DynamicPlan": [ + "TableReader 3323.33 root partition:p0,p1 data:Selection", + "└─Selection 3323.33 cop[tikv] lt(list_partition_pruning.tcollist.a, 6)", + " └─TableFullScan 10000.00 cop[tikv] table:tcollist keep order:false, stats:pseudo" + ], + "StaticPlan": [ + "PartitionUnion 6646.67 root ", + "├─TableReader 3323.33 root data:Selection", + "│ └─Selection 3323.33 cop[tikv] lt(list_partition_pruning.tcollist.a, 6)", + "│ └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p0 keep order:false, stats:pseudo", + "└─TableReader 3323.33 root data:Selection", + " └─Selection 3323.33 cop[tikv] lt(list_partition_pruning.tcollist.a, 6)", + " └─TableFullScan 10000.00 cop[tikv] table:tcollist, partition:p1 keep order:false, stats:pseudo" + ] + }, { "SQL": "explain format = 'brief' select * from tlist where a=0 or a=7", "DynamicPlan": [ diff --git a/pkg/planner/core/logical_plan_trace_test.go b/pkg/planner/core/logical_plan_trace_test.go index 3cfcc594a698a..a904223bc1e65 100644 --- a/pkg/planner/core/logical_plan_trace_test.go +++ b/pkg/planner/core/logical_plan_trace_test.go @@ -194,8 +194,8 @@ func TestSingleRuleTraceStep(t *testing.T) { assertRuleName: "partition_processor", assertRuleSteps: []assertTraceStep{ { - assertReason: "DataSource_1 has multiple needed partitions[p1,p2] after pruning", - assertAction: "DataSource_1 becomes PartitionUnion_6 with children[TableScan_7,TableScan_8]", + assertReason: "DataSource_1 doesn't have needed partition table after pruning", + assertAction: "DataSource_1 becomes TableDual_4", }, }, }, diff --git a/pkg/planner/core/rule_partition_processor.go b/pkg/planner/core/rule_partition_processor.go index 524110d683c86..adf30ffbbcaf7 100644 --- a/pkg/planner/core/rule_partition_processor.go +++ b/pkg/planner/core/rule_partition_processor.go @@ -781,25 +781,37 @@ func (l *listPartitionPruner) findUsedListPartitions(conds []expression.Expressi used := make(map[int]struct{}, len(ranges)) tc := l.ctx.GetSessionVars().StmtCtx.TypeCtx() for _, r := range ranges { - if !r.IsPointNullable(tc) { - return l.fullRange, nil - } if len(r.HighVal) != len(exprCols) { return l.fullRange, nil } - value, isNull, err := pruneExpr.EvalInt(l.ctx.GetExprCtx().GetEvalCtx(), chunk.MutRowFromDatums(r.HighVal).ToRow()) - if err != nil { - return nil, err - } - partitionIdx := l.listPrune.LocatePartition(value, isNull) - partitionIdx = l.pi.GetOverlappingDroppingPartitionIdx(partitionIdx) - if partitionIdx == -1 { - continue + var idxs map[int]struct{} + if !r.IsPointNullable(tc) { + // Only support `pruneExpr` is a Column + if _, ok := pruneExpr.(*expression.Column); !ok { + return l.fullRange, nil + } + idxs, err = l.listPrune.LocatePartitionByRange(l.ctx.GetExprCtx().GetEvalCtx(), r) + if err != nil { + return nil, err + } + } else { + value, isNull, err := pruneExpr.EvalInt(l.ctx.GetExprCtx().GetEvalCtx(), chunk.MutRowFromDatums(r.HighVal).ToRow()) + if err != nil { + return nil, err + } + idxs = make(map[int]struct{}) + idxs[l.listPrune.LocatePartition(l.ctx.GetExprCtx().GetEvalCtx(), value, isNull)] = struct{}{} } - if len(l.partitionNames) > 0 && !l.findByName(l.partitionNames, l.pi.Definitions[partitionIdx].Name.L) { - continue + for idx := range idxs { + idx = l.pi.GetOverlappingDroppingPartitionIdx(idx) + if idx == -1 { + continue + } + if len(l.partitionNames) > 0 && !l.findByName(l.partitionNames, l.pi.Definitions[idx].Name.L) { + continue + } + used[idx] = struct{}{} } - used[partitionIdx] = struct{}{} } return used, nil } diff --git a/pkg/table/tables/partition.go b/pkg/table/tables/partition.go index 5da631be92d20..a6b05f8f5c36c 100644 --- a/pkg/table/tables/partition.go +++ b/pkg/table/tables/partition.go @@ -29,6 +29,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/pkg/errctx" "github.com/pingcap/tidb/pkg/expression" + "github.com/pingcap/tidb/pkg/expression/exprctx" "github.com/pingcap/tidb/pkg/expression/exprstatic" "github.com/pingcap/tidb/pkg/kv" "github.com/pingcap/tidb/pkg/meta/model" @@ -424,8 +425,8 @@ type ForListPruning struct { PruneExpr expression.Expression // PruneExprCols is the columns of PruneExpr, it has removed the duplicate columns. PruneExprCols []*expression.Column - // valueMap is column value -> partition idx, uses to locate list partition. - valueMap map[int64]int + // valueToPartitionIdxBTree is column value -> partition idx, uses to locate list partition. + valueToPartitionIdxBTree *btree.BTreeG[*btreeListItem] // nullPartitionIdx is the partition idx for null value. nullPartitionIdx int // defaultPartitionIdx is the partition idx for default value/fallback. @@ -435,6 +436,11 @@ type ForListPruning struct { ColPrunes []*ForListColumnPruning } +type btreeListItem struct { + key uint64 + partitionIdx int +} + // btreeListColumnItem is BTree's Item that uses string to compare. type btreeListColumnItem struct { key string @@ -963,7 +969,7 @@ func (lp *ForListPruning) buildListColumnsPruner(ctx expression.BuildContext, // colIdx is the column index in the list columns. func (lp *ForListPruning) buildListPartitionValueMap(ctx expression.BuildContext, defs []model.PartitionDefinition, schema *expression.Schema, names types.NameSlice, p *parser.Parser) error { - lp.valueMap = map[int64]int{} + lp.valueToPartitionIdxBTree = btree.NewG[*btreeListItem](btreeDegree, func(a, b *btreeListItem) bool { return a.key < b.key }) lp.nullPartitionIdx = -1 lp.defaultPartitionIdx = -1 for partitionIdx, def := range defs { @@ -984,25 +990,82 @@ func (lp *ForListPruning) buildListPartitionValueMap(ctx expression.BuildContext lp.nullPartitionIdx = partitionIdx continue } - lp.valueMap[v] = partitionIdx + if mysql.HasUnsignedFlag(lp.PruneExpr.GetType(ctx.GetEvalCtx()).GetFlag()) { + lp.valueToPartitionIdxBTree.ReplaceOrInsert(&btreeListItem{uint64(v), partitionIdx}) + } else { + lp.valueToPartitionIdxBTree.ReplaceOrInsert(&btreeListItem{codec.EncodeIntToCmpUint(v), partitionIdx}) + } } } return nil } // LocatePartition locates partition by the column value -func (lp *ForListPruning) LocatePartition(value int64, isNull bool) int { +func (lp *ForListPruning) LocatePartition(ctx exprctx.EvalContext, value int64, isNull bool) int { if isNull { if lp.nullPartitionIdx >= 0 { return lp.nullPartitionIdx } return lp.defaultPartitionIdx } - partitionIdx, ok := lp.valueMap[value] + var key uint64 + if mysql.HasUnsignedFlag(lp.PruneExpr.GetType(ctx).GetFlag()) { + key = uint64(value) + } else { + key = codec.EncodeIntToCmpUint(value) + } + partitionIdx, ok := lp.valueToPartitionIdxBTree.Get(&btreeListItem{key: key}) if !ok { return lp.defaultPartitionIdx } - return partitionIdx + return partitionIdx.partitionIdx +} + +// LocatePartitionByRange locates partition by the range +// Only could process `column op value` right now. +func (lp *ForListPruning) LocatePartitionByRange(ctx exprctx.EvalContext, r *ranger.Range) (idxs map[int]struct{}, err error) { + lowVal, highVal := r.LowVal[0], r.HighVal[0] + if r.LowVal[0].Kind() == types.KindMinNotNull { + lowVal = types.GetMinValue(lp.PruneExpr.GetType(ctx)) + } + + if r.HighVal[0].Kind() == types.KindMaxValue { + highVal = types.GetMaxValue(lp.PruneExpr.GetType(ctx)) + } + + highInt64, _, err := lp.PruneExpr.EvalInt(ctx, chunk.MutRowFromDatums([]types.Datum{highVal}).ToRow()) + if err != nil { + return nil, err + } + + lowInt64, _, err := lp.PruneExpr.EvalInt(ctx, chunk.MutRowFromDatums([]types.Datum{lowVal}).ToRow()) + if err != nil { + return nil, err + } + + var lowKey, highKey uint64 + + if mysql.HasUnsignedFlag(lp.PruneExpr.GetType(ctx).GetFlag()) { + lowKey, highKey = uint64(lowInt64), uint64(highInt64) + } else { + lowKey, highKey = codec.EncodeIntToCmpUint(lowInt64), codec.EncodeIntToCmpUint(highInt64) + } + + idxs = make(map[int]struct{}) + lp.valueToPartitionIdxBTree.AscendRange(&btreeListItem{key: lowKey}, &btreeListItem{key: highKey}, func(item *btreeListItem) bool { + if item.key == lowKey && r.LowExclude { + return true + } + idxs[item.partitionIdx] = struct{}{} + return true + }) + + if item, ok := lp.valueToPartitionIdxBTree.Get(&btreeListItem{key: highKey}); ok && !r.HighExclude { + idxs[item.partitionIdx] = struct{}{} + } + + idxs[lp.defaultPartitionIdx] = struct{}{} + return idxs, nil } func (lp *ForListPruning) locateListPartitionByRow(ctx expression.EvalContext, r []types.Datum) (int, error) { @@ -1010,7 +1073,7 @@ func (lp *ForListPruning) locateListPartitionByRow(ctx expression.EvalContext, r if err != nil { return -1, errors.Trace(err) } - idx := lp.LocatePartition(value, isNull) + idx := lp.LocatePartition(ctx, value, isNull) if idx >= 0 { return idx, nil } diff --git a/tests/integrationtest/r/planner/core/casetest/partition/integration_partition.result b/tests/integrationtest/r/planner/core/casetest/partition/integration_partition.result index 7cb1fa7f4692a..6e62a8bd6392d 100644 --- a/tests/integrationtest/r/planner/core/casetest/partition/integration_partition.result +++ b/tests/integrationtest/r/planner/core/casetest/partition/integration_partition.result @@ -634,17 +634,7 @@ Projection 10.00 root list_partition_pruning.trange.a └─TableRangeScan 10.00 cop[tikv] table:trange, partition:p3 range:(10,+inf], keep order:true, stats:pseudo explain format='brief' select a from tlist use index () where b > 10 order by b limit 10; id estRows task access object operator info -Projection 10.00 root list_partition_pruning.tlist.a -└─TopN 10.00 root list_partition_pruning.tlist.b, offset:0, count:10 - └─PartitionUnion 20.00 root - ├─Limit 10.00 root offset:0, count:10 - │ └─TableReader 10.00 root data:Limit - │ └─Limit 10.00 cop[tikv] offset:0, count:10 - │ └─TableRangeScan 10.00 cop[tikv] table:tlist, partition:p0 range:(10,+inf], keep order:true, stats:pseudo - └─Limit 10.00 root offset:0, count:10 - └─TableReader 10.00 root data:Limit - └─Limit 10.00 cop[tikv] offset:0, count:10 - └─TableRangeScan 10.00 cop[tikv] table:tlist, partition:p1 range:(10,+inf], keep order:true, stats:pseudo +TableDual 0.00 root rows:0 explain format='brief' select a from thash use index () where b > 10 order by b limit 10; id estRows task access object operator info Projection 10.00 root list_partition_pruning.thash.a diff --git a/tests/integrationtest/r/planner/core/integration_partition.result b/tests/integrationtest/r/planner/core/integration_partition.result index 5860055f294a5..5adfd02941234 100644 --- a/tests/integrationtest/r/planner/core/integration_partition.result +++ b/tests/integrationtest/r/planner/core/integration_partition.result @@ -1296,3 +1296,25 @@ explain select *,_tidb_rowid from t partition(p0,p1) where _tidb_rowid=1; id estRows task access object operator info TableReader_6 10000.00 root partition:p0,p1 data:TableRangeScan_5 └─TableRangeScan_5 10000.00 cop[tikv] table:t range:[1,1], keep order:false, stats:pseudo +drop table if exists t; +CREATE TABLE `t` ( +`a` bigint unsigned +) +PARTITION BY LIST (`a`) +(PARTITION `p0` VALUES IN (18446744073709551610,1), +PARTITION `p1` VALUES IN (2,3)); +explain select * from t where a < 18446744073709551610 and a > 2; +id estRows task access object operator info +TableReader_7 250.00 root partition:p1 data:Selection_6 +└─Selection_6 250.00 cop[tikv] gt(planner__core__integration_partition.t.a, 2), lt(planner__core__integration_partition.t.a, 18446744073709551610) + └─TableFullScan_5 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +explain select * from t where a < 18446744073709551610; +id estRows task access object operator info +TableReader_7 3323.33 root partition:all data:Selection_6 +└─Selection_6 3323.33 cop[tikv] lt(planner__core__integration_partition.t.a, 18446744073709551610) + └─TableFullScan_5 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +explain select * from t where a not in (18446744073709551610, 1); +id estRows task access object operator info +TableReader_7 3833.33 root partition:p1 data:Selection_6 +└─Selection_6 3833.33 cop[tikv] not(in(planner__core__integration_partition.t.a, 18446744073709551610, 1)) + └─TableFullScan_5 10000.00 cop[tikv] table:t keep order:false, stats:pseudo diff --git a/tests/integrationtest/t/planner/core/integration_partition.test b/tests/integrationtest/t/planner/core/integration_partition.test index 0e7ba235383b4..12e2578af2b19 100644 --- a/tests/integrationtest/t/planner/core/integration_partition.test +++ b/tests/integrationtest/t/planner/core/integration_partition.test @@ -864,3 +864,15 @@ select *,_tidb_rowid from t partition(p1) where _tidb_rowid=1; explain select *,_tidb_rowid from t partition(p0,p1) where _tidb_rowid=1; +# TestUnsignedBigintListPartitionPrune +drop table if exists t; +CREATE TABLE `t` ( + `a` bigint unsigned +) +PARTITION BY LIST (`a`) +(PARTITION `p0` VALUES IN (18446744073709551610,1), + PARTITION `p1` VALUES IN (2,3)); +explain select * from t where a < 18446744073709551610 and a > 2; +explain select * from t where a < 18446744073709551610; +explain select * from t where a not in (18446744073709551610, 1); +