planner: generate BatchPointGet for hash table partitions (#23733)

This commit is contained in:
Kenan Yao
2021-04-13 15:09:51 +08:00
committed by GitHub
parent c709217ff4
commit d339eb15eb
7 changed files with 514 additions and 40 deletions

View File

@ -49,6 +49,8 @@ type BatchPointGetExec struct {
handles []kv.Handle
physIDs []int64
partPos int
singlePart bool
partTblID int64
idxVals [][]types.Datum
startTS uint64
snapshotTS uint64
@ -211,6 +213,10 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
}
physID := getPhysID(e.tblInfo, idxVals[e.partPos].GetInt64())
// If this BatchPointGetExec is built only for the specific table partition, skip those filters not matching this partition.
if e.singlePart && e.partTblID != physID {
continue
}
idxKey, err1 := EncodeUniqueIndexKey(e.ctx, e.tblInfo, e.idxInfo, idxVals, physID)
if err1 != nil && !kv.ErrNotExist.Equal(err1) {
return err1
@ -326,7 +332,8 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
sort.Slice(e.handles, less)
}
keys := make([]kv.Key, len(e.handles))
keys := make([]kv.Key, 0, len(e.handles))
newHandles := make([]kv.Handle, 0, len(e.handles))
for i, handle := range e.handles {
var tID int64
if len(e.physIDs) > 0 {
@ -342,9 +349,15 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
tID = getPhysID(e.tblInfo, d.GetInt64())
}
}
// If this BatchPointGetExec is built only for the specific table partition, skip those handles not matching this partition.
if e.singlePart && e.partTblID != tID {
continue
}
key := tablecodec.EncodeRowKeyWithHandle(tID, handle)
keys[i] = key
keys = append(keys, key)
newHandles = append(newHandles, handle)
}
e.handles = newHandles
var values map[string][]byte
// Lock keys (include exists and non-exists keys) before fetch all values for Repeatable Read Isolation.

View File

@ -3901,6 +3901,8 @@ func (b *executorBuilder) buildBatchPointGet(plan *plannercore.BatchPointGetPlan
lock: plan.Lock,
waitTime: plan.LockWaitTime,
partPos: plan.PartitionColPos,
singlePart: plan.SinglePart,
partTblID: plan.PartTblID,
columns: plan.Columns,
}
if e.lock {

View File

@ -251,30 +251,3 @@ func (s *globalIndexSuite) TestIssue21731(c *C) {
tk.MustExec("drop table if exists p, t")
tk.MustExec("create table t (a int, b int, unique index idx(a)) partition by list columns(b) (partition p0 values in (1), partition p1 values in (2));")
}
func (s *globalIndexSuite) TestBatchPointGetTablePartition(c *C) {
testKit := testkit.NewTestKitWithInit(c, s.store)
testKit.MustExec("use test")
testKit.MustExec("drop table if exists t")
testKit.MustExec("create table t(a int, b int, primary key(a,b)) partition by hash(b) partitions 2")
testKit.MustExec("insert into t values(1,1),(1,2),(2,1),(2,2)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustQuery("select * from t where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("select * from t where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
testKit.MustQuery("select * from t where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("select * from t where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
}

View File

@ -996,3 +996,248 @@ func (s *testAnalyzeSuite) TestLimitIndexEstimation(c *C) {
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func (s *testAnalyzeSuite) TestBatchPointGetTablePartition(c *C) {
store, dom, err := newStoreWithBootstrap()
c.Assert(err, IsNil)
testKit := testkit.NewTestKit(c, store)
defer func() {
dom.Close()
store.Close()
}()
testKit.MustExec("use test")
testKit.MustExec("drop table if exists t1,t2,t3,t4,t5,t6")
testKit.MustExec("create table t1(a int, b int, primary key(a,b)) partition by hash(b) partitions 2")
testKit.MustExec("insert into t1 values(1,1),(1,2),(2,1),(2,2)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustQuery("explain format = 'brief' select * from t1 where a in (1,2) and b = 1").Check(testkit.Rows(
"Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false",
))
testKit.MustQuery("select * from t1 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t1 where a = 1 and b in (1,2)").Check(testkit.Rows(
"PartitionUnion 4.00 root ",
"├─Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false",
"└─Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false",
))
testKit.MustQuery("select * from t1 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
testKit.MustQuery("explain format = 'brief' select * from t1 where a in (1,2) and b = 1").Check(testkit.Rows(
"IndexReader 2.00 root partition:p1 index:IndexRangeScan",
"└─IndexRangeScan 2.00 cop[tikv] table:t1, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t1 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t1 where a = 1 and b in (1,2)").Check(testkit.Rows(
"IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan",
"└─IndexRangeScan 2.00 cop[tikv] table:t1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t1 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("create table t2(a int, b int, primary key(a,b)) partition by range(b) (partition p0 values less than (2), partition p1 values less than maxvalue)")
testKit.MustExec("insert into t2 values(1,1),(1,2),(2,1),(2,2)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustQuery("explain format = 'brief' select * from t2 where a in (1,2) and b = 1").Check(testkit.Rows(
"IndexReader 2.00 root index:IndexRangeScan",
"└─IndexRangeScan 2.00 cop[tikv] table:t2, partition:p0, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t2 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t2 where a = 1 and b in (1,2)").Check(testkit.Rows(
"PartitionUnion 4.00 root ",
"├─IndexReader 2.00 root index:IndexRangeScan",
"│ └─IndexRangeScan 2.00 cop[tikv] table:t2, partition:p0, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
"└─IndexReader 2.00 root index:IndexRangeScan",
" └─IndexRangeScan 2.00 cop[tikv] table:t2, partition:p1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t2 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
testKit.MustQuery("explain format = 'brief' select * from t2 where a in (1,2) and b = 1").Check(testkit.Rows(
"IndexReader 2.00 root partition:p0 index:IndexRangeScan",
"└─IndexRangeScan 2.00 cop[tikv] table:t2, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t2 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t2 where a = 1 and b in (1,2)").Check(testkit.Rows(
"IndexReader 2.00 root partition:all index:IndexRangeScan",
"└─IndexRangeScan 2.00 cop[tikv] table:t2, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t2 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
testKit.MustExec("create table t3(a int, b int, primary key(a,b)) partition by hash(b) partitions 2")
testKit.MustExec("insert into t3 values(1,1),(1,2),(2,1),(2,2)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustQuery("explain format = 'brief' select * from t3 where a in (1,2) and b = 1").Check(testkit.Rows(
"Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false",
))
testKit.MustQuery("select * from t3 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t3 where a = 1 and b in (1,2)").Check(testkit.Rows(
"PartitionUnion 4.00 root ",
"├─Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false",
"└─Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false",
))
testKit.MustQuery("select * from t3 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
testKit.MustQuery("explain format = 'brief' select * from t3 where a in (1,2) and b = 1").Check(testkit.Rows(
"TableReader 2.00 root partition:p1 data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t3 range:[1 1,1 1], [2 1,2 1], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t3 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t3 where a = 1 and b in (1,2)").Check(testkit.Rows(
"TableReader 2.00 root partition:p0,p1 data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t3 range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t3 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("create table t4(a int, b int, primary key(a,b)) partition by range(b) (partition p0 values less than (2), partition p1 values less than maxvalue)")
testKit.MustExec("insert into t4 values(1,1),(1,2),(2,1),(2,2)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustQuery("explain format = 'brief' select * from t4 where a in (1,2) and b = 1").Check(testkit.Rows(
"TableReader 2.00 root data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t4, partition:p0 range:[1 1,1 1], [2 1,2 1], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t4 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t4 where a = 1 and b in (1,2)").Check(testkit.Rows(
"PartitionUnion 4.00 root ",
"├─TableReader 2.00 root data:TableRangeScan",
"│ └─TableRangeScan 2.00 cop[tikv] table:t4, partition:p0 range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
"└─TableReader 2.00 root data:TableRangeScan",
" └─TableRangeScan 2.00 cop[tikv] table:t4, partition:p1 range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t4 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
testKit.MustQuery("explain format = 'brief' select * from t4 where a in (1,2) and b = 1").Check(testkit.Rows(
"TableReader 2.00 root partition:p0 data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t4 range:[1 1,1 1], [2 1,2 1], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t4 where a in (1,2) and b = 1").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("explain format = 'brief' select * from t4 where a = 1 and b in (1,2)").Check(testkit.Rows(
"TableReader 2.00 root partition:all data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t4 range:[1 1,1 1], [1 2,1 2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t4 where a = 1 and b in (1,2)").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustExec("create table t5(a int, b int, primary key(a)) partition by hash(a) partitions 2")
testKit.MustExec("insert into t5 values(1,0),(2,0),(3,0),(4,0)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustQuery("explain format = 'brief' select * from t5 where a in (1,2) and 1 = 1").Check(testkit.Rows(
"PartitionUnion 4.00 root ",
"├─Batch_Point_Get 2.00 root table:t5 handle:[1 2], keep order:false, desc:false",
"└─Batch_Point_Get 2.00 root table:t5 handle:[1 2], keep order:false, desc:false",
))
testKit.MustQuery("select * from t5 where a in (1,2) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"2 0",
))
testKit.MustQuery("explain format = 'brief' select * from t5 where a in (1,3) and 1 = 1").Check(testkit.Rows(
"Batch_Point_Get 2.00 root table:t5 handle:[1 3], keep order:false, desc:false",
))
testKit.MustQuery("select * from t5 where a in (1,3) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"3 0",
))
testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
testKit.MustQuery("explain format = 'brief' select * from t5 where a in (1,2) and 1 = 1").Check(testkit.Rows(
"TableReader 2.00 root partition:p0,p1 data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t5 range:[1,1], [2,2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t5 where a in (1,2) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"2 0",
))
testKit.MustQuery("explain format = 'brief' select * from t5 where a in (1,3) and 1 = 1").Check(testkit.Rows(
"TableReader 2.00 root partition:p1 data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t5 range:[1,1], [3,3], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t5 where a in (1,3) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"3 0",
))
testKit.MustExec("create table t6(a int, b int, primary key(a)) partition by range(a) (partition p0 values less than (3), partition p1 values less than maxvalue)")
testKit.MustExec("insert into t6 values(1,0),(2,0),(3,0),(4,0)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustQuery("explain format = 'brief' select * from t6 where a in (1,2) and 1 = 1").Check(testkit.Rows(
"TableReader 2.00 root data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t6, partition:p0 range:[1,1], [2,2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t6 where a in (1,2) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"2 0",
))
testKit.MustQuery("explain format = 'brief' select * from t6 where a in (1,3) and 1 = 1").Check(testkit.Rows(
"PartitionUnion 4.00 root ",
"├─TableReader 2.00 root data:TableRangeScan",
"│ └─TableRangeScan 2.00 cop[tikv] table:t6, partition:p0 range:[1,1], [3,3], keep order:false, stats:pseudo",
"└─TableReader 2.00 root data:TableRangeScan",
" └─TableRangeScan 2.00 cop[tikv] table:t6, partition:p1 range:[1,1], [3,3], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t6 where a in (1,3) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"3 0",
))
testKit.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
testKit.MustQuery("explain format = 'brief' select * from t6 where a in (1,2) and 1 = 1").Check(testkit.Rows(
"TableReader 2.00 root partition:p0 data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t6 range:[1,1], [2,2], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t6 where a in (1,2) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"2 0",
))
testKit.MustQuery("explain format = 'brief' select * from t6 where a in (1,3) and 1 = 1").Check(testkit.Rows(
"TableReader 2.00 root partition:all data:TableRangeScan",
"└─TableRangeScan 2.00 cop[tikv] table:t6 range:[1,1], [3,3], keep order:false, stats:pseudo",
))
testKit.MustQuery("select * from t6 where a in (1,3) and 1 = 1").Sort().Check(testkit.Rows(
"1 0",
"3 0",
))
}

View File

@ -694,21 +694,34 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter
p: dual,
}, cntPlan, nil
}
canConvertPointGet := (!ds.isPartition && len(path.Ranges) > 0) || (ds.isPartition && len(path.Ranges) == 1)
canConvertPointGet = canConvertPointGet && candidate.path.StoreType != kv.TiFlash
if !candidate.path.IsIntHandlePath {
canConvertPointGet = canConvertPointGet &&
candidate.path.Index.Unique && !candidate.path.Index.HasPrefixIndex()
idxColsLen := len(candidate.path.Index.Columns)
for _, ran := range candidate.path.Ranges {
canConvertPointGet := len(path.Ranges) > 0 && path.StoreType != kv.TiFlash
if canConvertPointGet && !path.IsIntHandlePath {
// We simply do not build [batch] point get for prefix indexes. This can be optimized.
canConvertPointGet = path.Index.Unique && !path.Index.HasPrefixIndex()
// If any range cannot cover all columns of the index, we cannot build [batch] point get.
idxColsLen := len(path.Index.Columns)
for _, ran := range path.Ranges {
if len(ran.LowVal) != idxColsLen {
canConvertPointGet = false
break
}
}
}
if ds.table.Meta().GetPartitionInfo() != nil && ds.ctx.GetSessionVars().UseDynamicPartitionPrune() {
canConvertPointGet = false
var hashPartColName *ast.ColumnName
if tblInfo := ds.table.Meta(); canConvertPointGet && tblInfo.GetPartitionInfo() != nil {
// We do not build [batch] point get for dynamic table partitions now. This can be optimized.
if ds.ctx.GetSessionVars().UseDynamicPartitionPrune() {
canConvertPointGet = false
} else if len(path.Ranges) > 1 {
// We can only build batch point get for hash partitions on a simple column now. This is
// decided by the current implementation of `BatchPointGetExec::initialize()`, specifically,
// the `getPhysID()` function. Once we optimize that part, we can come back and enable
// BatchPointGet plan for more cases.
hashPartColName = getHashPartitionColumnName(ds.ctx, tblInfo)
if hashPartColName == nil {
canConvertPointGet = false
}
}
}
if canConvertPointGet {
allRangeIsPoint := true
@ -723,7 +736,7 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter
if len(path.Ranges) == 1 {
pointGetTask = ds.convertToPointGet(prop, candidate)
} else {
pointGetTask = ds.convertToBatchPointGet(prop, candidate)
pointGetTask = ds.convertToBatchPointGet(prop, candidate, hashPartColName)
}
if !pointGetTask.invalid() {
cntPlan += 1
@ -1642,7 +1655,7 @@ func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candida
return rTsk
}
func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, candidate *candidatePath) task {
func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, candidate *candidatePath, hashPartColName *ast.ColumnName) task {
if !prop.IsEmpty() && !candidate.isMatchProp {
return invalidTask
}
@ -1658,6 +1671,8 @@ func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, ca
TblInfo: ds.TableInfo(),
KeepOrder: !prop.IsEmpty(),
Columns: ds.Columns,
SinglePart: ds.isPartition,
PartTblID: ds.physicalTableID,
}.Init(ds.ctx, ds.tableStats.ScaleByExpectCnt(accessCnt), ds.schema.Clone(), ds.names, ds.blockOffset)
if batchPointGetPlan.KeepOrder {
batchPointGetPlan.Desc = prop.SortItems[0].Desc
@ -1683,6 +1698,7 @@ func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, ca
batchPointGetPlan.IndexInfo = candidate.path.Index
batchPointGetPlan.IdxCols = candidate.path.IdxCols
batchPointGetPlan.IdxColLens = candidate.path.IdxColLens
batchPointGetPlan.PartitionColPos = getPartitionColumnPos(candidate.path.Index, hashPartColName)
for _, ran := range candidate.path.Ranges {
batchPointGetPlan.IndexValues = append(batchPointGetPlan.IndexValues, ran.LowVal)
}

View File

@ -262,6 +262,13 @@ type BatchPointGetPlan struct {
Lock bool
LockWaitTime int64
Columns []*model.ColumnInfo
// SinglePart indicates whether this BatchPointGetPlan is just for a single partition, instead of the whole partition table.
// If the BatchPointGetPlan is built in fast path, this value if false; if the plan is generated in physical optimization for a partition,
// this value would be true. This value would decide the behavior of BatchPointGetExec, i.e, whether to compute the table ID of the partition
// on the fly.
SinglePart bool
// PartTblID is the table ID for the specific table partition.
PartTblID int64
}
// Clone implements PhysicalPlan interface.

View File

@ -354,6 +354,224 @@ func (s *testPointGetSuite) TestCBOPointGet(c *C) {
}
}
func (s *testPointGetSuite) TestPartitionBatchPointGetPlanCache(c *C) {
testKit := testkit.NewTestKit(c, s.store)
orgEnable := core.PreparedPlanCacheEnabled()
defer func() {
core.SetPreparedPlanCache(orgEnable)
}()
core.SetPreparedPlanCache(true)
var err error
testKit.Se, err = session.CreateSession4TestWithOpt(s.store, &session.Opt{
PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64),
})
c.Assert(err, IsNil)
testKit.MustExec("use test")
testKit.MustExec("drop table if exists t")
testKit.MustExec("create table t(a int, b int, unique key(a))")
testKit.MustExec("insert into t values(1,1),(2,2),(3,3)")
testKit.MustExec("prepare stmt from 'select * from t use index(a) where (a >= ? and a <= ?) or a = 3'")
testKit.MustExec("set @p=1,@q=2,@u=3")
testKit.MustQuery("execute stmt using @p,@p").Sort().Check(testkit.Rows(
"1 1",
"3 3",
))
testKit.MustQuery("execute stmt using @u,@q").Sort().Check(testkit.Rows(
"3 3",
))
testKit.MustExec("drop table t")
testKit.MustExec("create table t(a int, b int, primary key(a,b)) partition by hash(b) partitions 2")
testKit.MustExec("insert into t values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)")
testKit.MustExec("set @@tidb_partition_prune_mode = 'static'")
testKit.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and b = ?'")
testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows(
"2 1",
))
testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows(
"2 2",
))
testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
"3 1",
))
testKit.MustQuery("execute stmt using @u,@p,@p").Sort().Check(testkit.Rows(
"2 1",
))
testKit.MustExec("prepare stmt from 'select * from t where a in (?,?) and b = ?'")
testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("execute stmt using @q,@p,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows(
"2 1",
))
testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows(
"1 2",
"2 2",
))
testKit.MustExec("prepare stmt from 'select * from t where a = ? and ((b >= ? and b <= ?) or b = 2)'")
testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows(
"1 2",
))
testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows(
"2 2",
))
testKit.MustQuery("execute stmt using @p,@p,@u").Sort().Check(testkit.Rows(
"1 1",
"1 2",
"1 3",
))
testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows(
"1 2",
))
testKit.MustExec("prepare stmt from 'select * from t where a = ? and b in (?,?)'")
testKit.MustQuery("execute stmt using @p,@p,@q").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows(
"1 2",
))
testKit.MustQuery("execute stmt using @q,@p,@q").Sort().Check(testkit.Rows(
"2 1",
"2 2",
))
testKit.Se.GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
testKit.MustExec("drop table t")
testKit.MustExec("create table t(a int, b int, primary key(a,b)) partition by hash(b) partitions 2")
testKit.MustExec("insert into t values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)")
testKit.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and b = ?'")
testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows(
"2 1",
))
testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows(
"2 2",
))
testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
"3 1",
))
testKit.MustQuery("execute stmt using @u,@p,@p").Sort().Check(testkit.Rows(
"2 1",
))
testKit.MustExec("prepare stmt from 'select * from t where a in (?,?) and b = ?'")
testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("execute stmt using @q,@p,@p").Sort().Check(testkit.Rows(
"1 1",
"2 1",
))
testKit.MustQuery("execute stmt using @q,@q,@p").Sort().Check(testkit.Rows(
"2 1",
))
testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows(
"1 2",
"2 2",
))
testKit.MustExec("prepare stmt from 'select * from t where a = ? and ((b >= ? and b <= ?) or b = 2)'")
testKit.MustQuery("execute stmt using @p,@p,@p").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows(
"1 2",
))
testKit.MustQuery("execute stmt using @q,@q,@q").Sort().Check(testkit.Rows(
"2 2",
))
testKit.MustQuery("execute stmt using @p,@p,@u").Sort().Check(testkit.Rows(
"1 1",
"1 2",
"1 3",
))
testKit.MustQuery("execute stmt using @p,@u,@p").Sort().Check(testkit.Rows(
"1 2",
))
testKit.MustExec("prepare stmt from 'select * from t where a = ? and b in (?,?)'")
testKit.MustQuery("execute stmt using @p,@p,@q").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustQuery("execute stmt using @p,@q,@p").Sort().Check(testkit.Rows(
"1 1",
"1 2",
))
testKit.MustQuery("execute stmt using @p,@q,@q").Sort().Check(testkit.Rows(
"1 2",
))
testKit.MustQuery("execute stmt using @q,@p,@q").Sort().Check(testkit.Rows(
"2 1",
"2 2",
))
testKit.MustExec("drop table t")
testKit.MustExec("create table t(a int, b int, primary key(a)) partition by hash(a) partitions 2")
testKit.MustExec("insert into t values(1,0),(2,0),(3,0),(4,0)")
testKit.MustExec("prepare stmt from 'select * from t where ((a >= ? and a <= ?) or a = 2) and 1 = 1'")
testKit.MustQuery("execute stmt using @p,@p").Sort().Check(testkit.Rows(
"1 0",
"2 0",
))
testKit.MustQuery("execute stmt using @q,@q").Sort().Check(testkit.Rows(
"2 0",
))
testKit.MustQuery("execute stmt using @p,@u").Sort().Check(testkit.Rows(
"1 0",
"2 0",
"3 0",
))
testKit.MustQuery("execute stmt using @u,@p").Sort().Check(testkit.Rows(
"2 0",
))
testKit.MustExec("prepare stmt from 'select * from t where a in (?,?) and 1 = 1'")
testKit.MustQuery("execute stmt using @p,@q").Sort().Check(testkit.Rows(
"1 0",
"2 0",
))
testKit.MustQuery("execute stmt using @q,@p").Sort().Check(testkit.Rows(
"1 0",
"2 0",
))
testKit.MustQuery("execute stmt using @q,@q").Sort().Check(testkit.Rows(
"2 0",
))
}
func (s *testPointGetSuite) TestBatchPointGetPlanCache(c *C) {
tk := testkit.NewTestKit(c, s.store)
orgEnable := core.PreparedPlanCacheEnabled()