167 lines
6.6 KiB
Go
167 lines
6.6 KiB
Go
// Copyright 2020 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 executor_test
|
|
|
|
import (
|
|
"fmt"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"github.com/pingcap/kvproto/pkg/keyspacepb"
|
|
"github.com/pingcap/tidb/pkg/config/kerneltype"
|
|
"github.com/pingcap/tidb/pkg/ddl"
|
|
"github.com/pingcap/tidb/pkg/keyspace"
|
|
"github.com/pingcap/tidb/pkg/kv"
|
|
"github.com/pingcap/tidb/pkg/sessionctx/vardef"
|
|
"github.com/pingcap/tidb/pkg/store/mockstore"
|
|
"github.com/pingcap/tidb/pkg/testkit"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func createSampleTestkit(t *testing.T, store kv.Storage) *testkit.TestKit {
|
|
atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1)
|
|
tk := testkit.NewTestKit(t, store)
|
|
tk.MustExec("drop database if exists test_table_sample;")
|
|
tk.MustExec("create database test_table_sample;")
|
|
tk.MustExec("use test_table_sample;")
|
|
tk.MustExec("set @@session.tidb_scatter_region='table';")
|
|
return tk
|
|
}
|
|
|
|
func TestTableSampleBasic(t *testing.T) {
|
|
store := testkit.CreateMockStore(t)
|
|
tk := createSampleTestkit(t, store)
|
|
tk.MustExec("create table t (a int);")
|
|
tk.Session().GetSessionVars().EnableClusteredIndex = vardef.ClusteredIndexDefModeOn
|
|
tk.MustQuery("select * from t tablesample regions();").Check(testkit.Rows())
|
|
|
|
tk.MustExec("insert into t values (0), (1000), (2000);")
|
|
tk.MustQuery("select * from t tablesample regions();").Check(testkit.Rows("0"))
|
|
tk.MustExec("alter table t add column b varchar(255) not null default 'abc';")
|
|
tk.MustQuery("select b from t tablesample regions();").Check(testkit.Rows("abc"))
|
|
tk.MustExec("alter table t add column c int as (a + 1);")
|
|
tk.MustQuery("select c from t tablesample regions();").Check(testkit.Rows("1"))
|
|
tk.MustQuery("select c, _tidb_rowid from t tablesample regions();").Check(testkit.Rows("1 1"))
|
|
tk.MustHavePlan("select * from t tablesample regions();", "TableSample")
|
|
|
|
tk.MustExec("drop table if exists t;")
|
|
tk.MustExec("create table t(a BIGINT PRIMARY KEY AUTO_RANDOM(3), b int auto_increment, key(b)) pre_split_regions=8;")
|
|
tk.MustQuery("select * from t tablesample regions();").Check(testkit.Rows())
|
|
for range 1000 {
|
|
tk.MustExec("insert into t values();")
|
|
}
|
|
tk.MustQuery("select count(*) from t tablesample regions();").Check(testkit.Rows("8"))
|
|
|
|
tk.MustExec("drop table if exists t;")
|
|
tk.MustExec("create table t(a varchar(30) collate utf8mb4_general_ci primary key);")
|
|
tk.MustQuery("split table t between ('a') and ('z') regions 100;").Check(testkit.Rows("99 1"))
|
|
tk.MustExec("insert into t values ('a'), ('b'), ('c'), ('d'), ('e');")
|
|
tk.MustQuery("select a from t tablesample regions() limit 2;").Check(testkit.Rows("a", "b"))
|
|
}
|
|
|
|
func TestTableSampleMultiRegions(t *testing.T) {
|
|
store := testkit.CreateMockStore(t)
|
|
tk := createSampleTestkit(t, store)
|
|
tk.MustExec("create table t (a int) shard_row_id_bits = 2 pre_split_regions = 2;")
|
|
for i := range 100 {
|
|
tk.MustExec("insert into t values (?);", i)
|
|
}
|
|
rows := tk.MustQuery("select * from t tablesample regions();").Rows()
|
|
require.Len(t, rows, 4)
|
|
tk.MustQuery("select a from t tablesample regions() order by a limit 1;").Check(testkit.Rows("0"))
|
|
tk.MustQuery("select a from t tablesample regions() where a = 0;").Check(testkit.Rows("0"))
|
|
|
|
tk.MustExec("create table t2 (a int) shard_row_id_bits = 2 pre_split_regions = 2;")
|
|
for i := range 100 {
|
|
tk.MustExec("insert into t2 values (?);", i)
|
|
}
|
|
rows = tk.MustQuery("select * from t tablesample regions(), t2 tablesample regions();").Rows()
|
|
require.Len(t, rows, 16)
|
|
tk.MustQuery("select count(*) from t tablesample regions();").Check(testkit.Rows("4"))
|
|
tk.MustExec("drop table t2;")
|
|
}
|
|
|
|
func TestTableSampleNoSplitTable(t *testing.T) {
|
|
store := testkit.CreateMockStore(t)
|
|
tk := createSampleTestkit(t, store)
|
|
atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0)
|
|
tk.MustExec("drop table if exists t1;")
|
|
tk.MustExec("drop table if exists t2;")
|
|
tk.MustExec("create table t1 (id int primary key);")
|
|
tk.MustExec("create table t2 (id int primary key);")
|
|
tk.MustExec("insert into t2 values(1);")
|
|
rows := tk.MustQuery("select * from t1 tablesample regions();").Rows()
|
|
rows2 := tk.MustQuery("select * from t2 tablesample regions();").Rows()
|
|
require.Len(t, rows, 0)
|
|
require.Len(t, rows2, 1)
|
|
}
|
|
|
|
func TestTableSamplePlan(t *testing.T) {
|
|
store := testkit.CreateMockStore(t)
|
|
tk := createSampleTestkit(t, store)
|
|
tk.MustExec("drop table if exists t;")
|
|
tk.MustExec("create table t (a bigint, b int default 10);")
|
|
tk.MustExec("split table t between (0) and (100000) regions 4;")
|
|
tk.MustExec("insert into t(a) values (1), (2), (3);")
|
|
rows := tk.MustQuery("explain analyze select a from t tablesample regions();").Rows()
|
|
require.Len(t, rows, 2)
|
|
tableSample := fmt.Sprintf("%v", rows[1])
|
|
require.Regexp(t, ".*TableSample.*", tableSample)
|
|
}
|
|
|
|
func TestMaxChunkSize(t *testing.T) {
|
|
store := testkit.CreateMockStore(t)
|
|
tk := createSampleTestkit(t, store)
|
|
tk.MustExec("create table t (a int) shard_row_id_bits = 2 pre_split_regions = 2;")
|
|
for i := range 100 {
|
|
tk.MustExec("insert into t values (?);", i)
|
|
}
|
|
tk.Session().GetSessionVars().MaxChunkSize = 1
|
|
rows := tk.MustQuery("select * from t tablesample regions();").Rows()
|
|
require.Len(t, rows, 4)
|
|
}
|
|
|
|
func TestKeyspaceSample(t *testing.T) {
|
|
if kerneltype.IsClassic() {
|
|
t.Skip("Keyspace is not supported in classic mode")
|
|
}
|
|
// Build an exist keyspace.
|
|
keyspaceMeta := keyspacepb.KeyspaceMeta{}
|
|
keyspaceMeta.Id = 2
|
|
keyspaceMeta.Name = keyspace.System
|
|
|
|
opts := mockstore.WithKeyspaceMeta(&keyspaceMeta)
|
|
store := testkit.CreateMockStore(t, opts)
|
|
tk := createSampleTestkit(t, store)
|
|
tk.MustExec("create table t (a int);")
|
|
tk.MustExec("insert into t values (1),(2);")
|
|
tk.MustQuery("select a from t;").Check(testkit.Rows("1", "2"))
|
|
|
|
// Build another exist keyspace.
|
|
keyspaceMeta02 := keyspacepb.KeyspaceMeta{}
|
|
keyspaceMeta02.Id = 3
|
|
keyspaceMeta02.Name = keyspace.System
|
|
|
|
opts02 := mockstore.WithKeyspaceMeta(&keyspaceMeta02)
|
|
store02 := testkit.CreateMockStore(t, opts02)
|
|
|
|
tk02 := createSampleTestkit(t, store02)
|
|
tk02.MustExec("create table t (a int);")
|
|
|
|
// Tables with the same name in different keyspaces have isolated data.
|
|
tk02.MustExec("insert into t values (3),(4);")
|
|
tk02.MustQuery("select a from t;").Check(testkit.Rows("3", "4"))
|
|
}
|