Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor: add test cases about partition table with expression #24628

Merged
merged 2 commits into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 248 additions & 7 deletions executor/partition_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,12 +573,12 @@ func (s *partitionTableSuite) TestGlobalStatsAndSQLBinding(c *C) {
}

func createTable4DynamicPruneModeTestWithExpression(tk *testkit.TestKit) {
tk.MustExec("create table trange(a int) partition by range(a) (partition p0 values less than(3), partition p1 values less than (5), partition p2 values less than(11));")
tk.MustExec("create table thash(a int) partition by hash(a) partitions 4;")
tk.MustExec("create table t(a int)")
tk.MustExec("insert into trange values(1), (1), (1), (2), (3), (4), (5), (6), (7), (7), (10), (NULL), (NULL);")
tk.MustExec("insert into thash values(1), (1), (1), (2), (3), (4), (5), (6), (7), (7), (10), (NULL), (NULL);")
tk.MustExec("insert into t values(1), (1), (1), (2), (3), (4), (5), (6), (7), (7), (10), (NULL), (NULL);")
tk.MustExec("create table trange(a int, b int) partition by range(a) (partition p0 values less than(3), partition p1 values less than (5), partition p2 values less than(11));")
tk.MustExec("create table thash(a int, b int) partition by hash(a) partitions 4;")
tk.MustExec("create table t(a int, b int)")
tk.MustExec("insert into trange values(1, NULL), (1, NULL), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (6, 7), (7, 7), (7, 7), (10, NULL), (NULL, NULL), (NULL, 1);")
tk.MustExec("insert into thash values(1, NULL), (1, NULL), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (6, 7), (7, 7), (7, 7), (10, NULL), (NULL, NULL), (NULL, 1);")
tk.MustExec("insert into t values(1, NULL), (1, NULL), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (6, 7), (7, 7), (7, 7), (10, NULL), (NULL, NULL), (NULL, 1);")
tk.MustExec("set session tidb_partition_prune_mode='dynamic'")
tk.MustExec("analyze table trange")
tk.MustExec("analyze table thash")
Expand All @@ -590,7 +590,7 @@ type testData4Expression struct {
partitions []string
}

func (s *partitionTableSuite) TestDynamicPruneModeWithEqualExpression(c *C) {
func (s *partitionTableSuite) TestDynamicPruneModeWithExpression(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop database if exists db_equal_expression")
tk.MustExec("create database db_equal_expression")
Expand Down Expand Up @@ -627,6 +627,247 @@ func (s *partitionTableSuite) TestDynamicPruneModeWithEqualExpression(c *C) {
"p0",
},
},
{
sql: "select * from %s where b is NULL",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a > -1",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a >= 4 and a <= 5",
partitions: []string{
"p1,p2",
"p0,p1",
},
},
{
sql: "select * from %s where a > 10",
partitions: []string{
"dual",
"all",
},
},
{
sql: "select * from %s where a >=2 and a <= 3",
partitions: []string{
"p0,p1",
"p2,p3",
},
},
{
sql: "select * from %s where a between 2 and 3",
partitions: []string{
"p0,p1",
"p2,p3",
},
},
{
sql: "select * from %s where a < 2",
partitions: []string{
"p0",
"all",
},
},
{
sql: "select * from %s where a <= 3",
partitions: []string{
"p0,p1",
"all",
},
},
{
sql: "select * from %s where a in (2, 3)",
partitions: []string{
"p0,p1",
"p2,p3",
},
},
{
sql: "select * from %s where a in (1, 5)",
partitions: []string{
"p0,p2",
"p1",
},
},
{
sql: "select * from %s where a not in (1, 5)",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a = 2 and a = 2",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be simplified by the optimiser before the pruning module is called? I am just curious :)

Copy link
Contributor

@qw4990 qw4990 May 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emm, actually no, there is no such a process in our optimizer to remove duplicated conditions.
They will be naturally handled in range calculation where all conditions are analyzed to generate some ranges to access. And in this case, the final range is [2, 2].

partitions: []string{
"p0",
"p2",
},
},
{
sql: "select * from %s where a = 2 and a = 3",
partitions: []string{
// This means that we have no partition-read plan
"",
"",
},
},
{
sql: "select * from %s where a < 2 and a > 0",
partitions: []string{
"p0",
"p1",
},
},
{
sql: "select * from %s where a < 2 and a < 3",
partitions: []string{
"p0",
"all",
},
},
{
sql: "select * from %s where a > 1 and a > 2",
partitions: []string{
"p1,p2",
"all",
},
},
{
sql: "select * from %s where a = 2 or a = 3",
partitions: []string{
"p0,p1",
"p2,p3",
},
},
{
sql: "select * from %s where a = 2 or a in (3)",
partitions: []string{
"p0,p1",
"p2,p3",
},
},
{
sql: "select * from %s where a = 2 or a > 3",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a = 2 or a <= 1",
partitions: []string{
"p0",
"all",
},
},
{
sql: "select * from %s where a = 2 or a between 2 and 2",
partitions: []string{
"p0",
"p2",
},
},
{
sql: "select * from %s where a != 2",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a != 2 and a > 4",
partitions: []string{
"p2",
"all",
},
},
{
sql: "select * from %s where a != 2 and a != 3",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a != 2 and a = 3",
partitions: []string{
"p1",
"p3",
},
},
{
sql: "select * from %s where not (a = 2)",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where not (a > 2)",
partitions: []string{
"p0",
"all",
},
},
{
sql: "select * from %s where not (a < 2)",
partitions: []string{
"all",
"all",
},
},
// cases that partition pruning can not work
{
sql: "select * from %s where a + 1 > 4",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a - 1 > 0",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a * 2 < 0",
partitions: []string{
"all",
"all",
},
},
{
sql: "select * from %s where a << 1 < 0",
partitions: []string{
"all",
"all",
},
},
// comparison between int column and string column
{
sql: "select * from %s where a > '10'",
partitions: []string{
"dual",
"all",
},
},
{
sql: "select * from %s where a > '10ab'",
partitions: []string{
"dual",
"all",
},
},
}

for _, t := range tests {
Expand Down
7 changes: 5 additions & 2 deletions util/testkit/testkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,12 @@ func (tk *TestKit) MustNoGlobalStats(table string) bool {
// MustPartition checks if the result execution plan must read specific partitions.
func (tk *TestKit) MustPartition(sql string, partitions string, args ...interface{}) *Result {
rs := tk.MustQuery("explain "+sql, args...)
ok := false
ok := len(partitions) == 0
for i := range rs.rows {
if strings.Compare(rs.rows[i][3], "partition:"+partitions) == 0 {
if len(partitions) == 0 && strings.Contains(rs.rows[i][3], "partition:") {
ok = false
}
if len(partitions) != 0 && strings.Compare(rs.rows[i][3], "partition:"+partitions) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While changing this, maybe use '==' for string comparison instead?
(See comment in strings.Compare() function)

Also how would it handle the 'table:' part in the access object column (in case tidb_partition_prune_mode is not 'dynamic'?

explain select * from trange where a = 2 and a = 2
--------------

+-------------------------+----------+-----------+----------------------------+--------------------------------------------+
| id                      | estRows  | task      | access object              | operator info                              |
+-------------------------+----------+-----------+----------------------------+--------------------------------------------+
| TableReader_9           | 10.00    | root      |                            | data:Selection_8                           |
| └─Selection_8           | 10.00    | cop[tikv] |                            | eq(test.trange.a, 2), eq(test.trange.a, 2) |
|   └─TableFullScan_7     | 10000.00 | cop[tikv] | table:trange, partition:p0 | keep order:false, stats:pseudo             |
+-------------------------+----------+-----------+----------------------------+--------------------------------------------+

ok = true
}
}
Expand Down