Skip to content

Commit c17d86b

Browse files
author
Nimita Joshi
committed
Bug#37397306 - looks like not use pruning when it inserts with now()
function in 8.0. Issue: All partitions are being retrieved when inserting the now() value into a non-partition key column in a partition table. Analysis: In case of an INSERT query partition pruning takes place in the prepare stage only. now() was changed from being const to const_for_execution due to which pruning cannot take place as it requires all the values in the INSERT to be const. Fix: Enable partition pruning to be performed at the execution stage. Change-Id: I68b7d9d3d880c873a880991d564eca1975900dd0
1 parent 00e9ed1 commit c17d86b

9 files changed

+357
-91
lines changed

mysql-test/r/explain_dml.result

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@ Warning 3005 INSERT DELAYED is no longer supported. The statement was converted
9595
Note 1003 insert ignore into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`,`test`.`t1`.`c2`) /* select#1 */ select `test`.`t2`.`c1` AS `c1`,'a' AS `a` from `test`.`t2` on duplicate key update `test`.`t1`.`c2` = 'c'
9696
EXPLAIN
9797
INSERT INTO t1 PARTITION(p0, p1)
98-
SET c1 = (SELECT c1 from t2);
98+
SET c1 = (SELECT c1 from t2 LIMIT 1);
9999
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
100-
1 INSERT t1 p0_subp0,p0_subp1,p1_subp6,p1_subp7 ALL NULL NULL NULL NULL NULL NULL NULL
100+
1 INSERT t1 p1_subp6 ALL NULL NULL NULL NULL NULL NULL NULL
101101
2 SUBQUERY t2 NULL ALL NULL NULL NULL NULL 3 100.00 NULL
102102
Warnings:
103-
Note 1003 insert into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2`))
103+
Note 1003 insert into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` limit 1))
104104
EXPLAIN
105105
REPLACE LOW_PRIORITY INTO t1 PARTITION(p0, p1) (c1, c2)
106106
VALUES (1, 'a'), (2, 'b');
@@ -119,12 +119,12 @@ Warning 3005 REPLACE DELAYED is no longer supported. The statement was converted
119119
Note 1003 replace into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`,`test`.`t1`.`c2`) /* select#1 */ select `test`.`t2`.`c1` AS `c1`,'a' AS `a` from `test`.`t2`
120120
EXPLAIN
121121
REPLACE INTO t1 PARTITION(p0, p1)
122-
SET c1 = (SELECT c1 from t2);
122+
SET c1 = (SELECT c1 from t2 LIMIT 1);
123123
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
124-
1 REPLACE t1 p0_subp0,p0_subp1,p1_subp6,p1_subp7 ALL NULL NULL NULL NULL NULL NULL NULL
124+
1 REPLACE t1 p1_subp6 ALL NULL NULL NULL NULL NULL NULL NULL
125125
2 SUBQUERY t2 NULL ALL NULL NULL NULL NULL 3 100.00 NULL
126126
Warnings:
127-
Note 1003 replace into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2`))
127+
Note 1003 replace into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` limit 1))
128128
EXPLAIN FORMAT=TRADITIONAL FOR QUERY 'DELETE FROM t3 WHERE c1 > 0'
129129
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
130130
1 DELETE t3 NULL ALL NULL NULL NULL NULL 3 100.00 Using where

mysql-test/r/partition_locking.result

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4784,14 +4784,17 @@ FLUSH STATUS;
47844784
EXPLAIN INSERT INTO t2 VALUES ((SELECT max(a) FROM t1),
47854785
(SELECT min(a) FROM t1));
47864786
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
4787-
1 INSERT t2 p0,p1,p2 ALL NULL NULL NULL NULL # NULL NULL
4787+
1 INSERT t2 p2 ALL NULL NULL NULL NULL # NULL NULL
47884788
3 SUBQUERY t1 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 NULL
47894789
2 SUBQUERY t1 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 NULL
47904790
Warnings:
47914791
Note 1003 insert into `test`.`t2` values ((/* select#2 */ select max(`test`.`t1`.`a`) from `test`.`t1`),(/* select#3 */ select min(`test`.`t1`.`a`) from `test`.`t1`))
47924792
VARIABLE_NAME VARIABLE_VALUE
47934793
Handler_commit 1
47944794
Handler_external_lock 6
4795+
Handler_read_first 3
4796+
Handler_read_key 3
4797+
Handler_read_rnd_next 8
47954798
# I.e. No lock pruning possible
47964799
FLUSH STATUS;
47974800
INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1),
@@ -4809,14 +4812,17 @@ FLUSH STATUS;
48094812
EXPLAIN INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1),
48104813
(SELECT b FROM t1 WHERE a = 2));
48114814
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
4812-
1 INSERT t2 p0,p1,p2 ALL NULL NULL NULL NULL # NULL NULL
4815+
1 INSERT t2 p1 ALL NULL NULL NULL NULL # NULL NULL
48134816
3 SUBQUERY t1 p2 ALL NULL NULL NULL NULL # 25.00 Using where
48144817
2 SUBQUERY t1 p1 ALL NULL NULL NULL NULL # 25.00 Using where
48154818
Warnings:
48164819
Note 1003 insert into `test`.`t2` values ((/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` where (`test`.`t1`.`a` = 1)),(/* select#3 */ select `test`.`t1`.`b` from `test`.`t1` where (`test`.`t1`.`a` = 2)))
48174820
VARIABLE_NAME VARIABLE_VALUE
48184821
Handler_commit 1
48194822
Handler_external_lock 6
4823+
Handler_read_first 1
4824+
Handler_read_key 1
4825+
Handler_read_rnd_next 4
48204826
# I.e. No lock pruning possible on insert table
48214827
SELECT * FROM t2 ORDER BY a, b;
48224828
a b

mysql-test/r/partition_pruning.result

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6327,3 +6327,116 @@ c1 c2
63276327
SELECT * from t2 WHERE c2 NOT IN ((SELECT c0 FROM t1 LIMIT 1),null);
63286328
c1 c2
63296329
DROP TABLE t1, t2;
6330+
#
6331+
# Bug#37397306 - looks like not use pruning when it inserts with now() function in 8.0
6332+
#
6333+
CREATE TABLE t1 (
6334+
f1 DATETIME NOT NULL,
6335+
f2 INT NOT NULL,
6336+
f3 DATE NOT NULL,
6337+
PRIMARY KEY (f1,f2)
6338+
)
6339+
PARTITION BY RANGE COLUMNS(f1)
6340+
(
6341+
PARTITION p01 VALUES LESS THAN ('1975-12-31 10:21:55'),
6342+
PARTITION p02 VALUES LESS THAN ('1976-12-31 10:21:55'),
6343+
PARTITION p03 VALUES LESS THAN ('2090-12-31 10:21:55')
6344+
);
6345+
ANALYZE TABLE t1;
6346+
Table Op Msg_type Msg_text
6347+
test.t1 analyze status OK
6348+
SET TIMESTAMP=UNIX_TIMESTAMP('2019-03-11 12:00:00');
6349+
EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'1976-11-31');
6350+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6351+
1 INSERT t1 p03 ALL NULL NULL NULL NULL NULL NULL NULL
6352+
Warnings:
6353+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`f1`,`test`.`t1`.`f2`,`test`.`t1`.`f3`) values (now(),10001,'1976-11-31')
6354+
SET TIMESTAMP=UNIX_TIMESTAMP('1975-03-11 12:00:00');
6355+
EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'2000-11-31');
6356+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6357+
1 INSERT t1 p01 ALL NULL NULL NULL NULL NULL NULL NULL
6358+
Warnings:
6359+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`f1`,`test`.`t1`.`f2`,`test`.`t1`.`f3`) values (now(),10001,'2000-11-31')
6360+
SET TIMESTAMP=DEFAULT;
6361+
DROP TABLE t1;
6362+
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER)
6363+
PARTITION BY RANGE (a)
6364+
(
6365+
PARTITION p1 VALUES LESS THAN (10),
6366+
PARTITION p2 VALUES LESS THAN MAXVALUE
6367+
);
6368+
ANALYZE TABLE t1;
6369+
Table Op Msg_type Msg_text
6370+
test.t1 analyze status OK
6371+
set @a=1,@b=22;
6372+
EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b);
6373+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6374+
1 INSERT t1 p1 ALL NULL NULL NULL NULL NULL NULL NULL
6375+
Warnings:
6376+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values ((@`a`),(@`b`))
6377+
EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2);
6378+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6379+
1 INSERT t1 p1,p2 ALL NULL NULL NULL NULL NULL NULL NULL
6380+
Warnings:
6381+
Note 1003 insert into `test`.`t1` values ((@`a`),1),((@`b`),2)
6382+
set @a=11,@b=22;
6383+
EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b);
6384+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6385+
1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL
6386+
Warnings:
6387+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values ((@`a`),(@`b`))
6388+
EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2);
6389+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6390+
1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL
6391+
Warnings:
6392+
Note 1003 insert into `test`.`t1` values ((@`a`),1),((@`b`),2)
6393+
PREPARE s from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,?)";
6394+
set @a=1,@b=22;
6395+
EXECUTE s USING @a,@b;
6396+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6397+
1 INSERT t1 p1 ALL NULL NULL NULL NULL NULL NULL NULL
6398+
Warnings:
6399+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,?)
6400+
set @a=11,@b=22;
6401+
EXECUTE s USING @a,@b;
6402+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6403+
1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL
6404+
Warnings:
6405+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,?)
6406+
PREPARE p from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,1), (?,2)";
6407+
set @a=1,@b=22;
6408+
EXECUTE p USING @a,@b;
6409+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6410+
1 INSERT t1 p1,p2 ALL NULL NULL NULL NULL NULL NULL NULL
6411+
Warnings:
6412+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,1),(?,2)
6413+
set @a=11,@b=22;
6414+
EXECUTE p USING @a,@b;
6415+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6416+
1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL
6417+
Warnings:
6418+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,1),(?,2)
6419+
DROP TABLE t1;
6420+
CREATE TABLE t1 (
6421+
id INT PRIMARY KEY,
6422+
f1 FLOAT
6423+
)
6424+
PARTITION BY RANGE (id)
6425+
(
6426+
PARTITION p0 VALUES LESS THAN (10),
6427+
PARTITION p1 VALUES LESS THAN MAXVALUE
6428+
);
6429+
ANALYZE TABLE t1;
6430+
Table Op Msg_type Msg_text
6431+
test.t1 analyze status OK
6432+
EXPLAIN INSERT INTO t1 (id, f1) VALUES (1,RAND());
6433+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6434+
1 INSERT t1 p0 ALL NULL NULL NULL NULL NULL NULL NULL
6435+
Warnings:
6436+
Note 1003 insert into `test`.`t1` (`test`.`t1`.`id`,`test`.`t1`.`f1`) values (1,rand())
6437+
EXPLAIN INSERT INTO t1 VALUES (20,RAND());
6438+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6439+
1 INSERT t1 p1 ALL NULL NULL NULL NULL NULL NULL NULL
6440+
Warnings:
6441+
Note 1003 insert into `test`.`t1` values (20,rand())
6442+
DROP TABLE t1;

mysql-test/t/explain_dml.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ INSERT DELAYED IGNORE INTO t1 PARTITION(p0, p1) (c1, c2)
7979
#INSERT .... SET
8080
EXPLAIN
8181
INSERT INTO t1 PARTITION(p0, p1)
82-
SET c1 = (SELECT c1 from t2);
82+
SET c1 = (SELECT c1 from t2 LIMIT 1);
8383

8484

8585
#REPLACE .... VALUES
@@ -95,7 +95,7 @@ REPLACE DELAYED INTO t1 PARTITION(p0, p1) (c1, c2)
9595
#REPLACE .... SET
9696
EXPLAIN
9797
REPLACE INTO t1 PARTITION(p0, p1)
98-
SET c1 = (SELECT c1 from t2);
98+
SET c1 = (SELECT c1 from t2 LIMIT 1);
9999

100100
#No effect on EXPLAIN FOR CONNECTION .... for both SINGLE/MULTI-TABLE DML
101101
let $QID= `SELECT CONNECTION_ID()`;

mysql-test/t/partition_pruning.test

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,3 +2510,79 @@ SELECT * from t2 WHERE c2 IN ((SELECT c0 FROM t1 LIMIT 1),null);
25102510
SELECT * from t2 WHERE c2 NOT IN ((SELECT c0 FROM t1 LIMIT 1),null);
25112511

25122512
DROP TABLE t1, t2;
2513+
2514+
--echo #
2515+
--echo # Bug#37397306 - looks like not use pruning when it inserts with now() function in 8.0
2516+
--echo #
2517+
2518+
CREATE TABLE t1 (
2519+
f1 DATETIME NOT NULL,
2520+
f2 INT NOT NULL,
2521+
f3 DATE NOT NULL,
2522+
PRIMARY KEY (f1,f2)
2523+
)
2524+
PARTITION BY RANGE COLUMNS(f1)
2525+
(
2526+
PARTITION p01 VALUES LESS THAN ('1975-12-31 10:21:55'),
2527+
PARTITION p02 VALUES LESS THAN ('1976-12-31 10:21:55'),
2528+
PARTITION p03 VALUES LESS THAN ('2090-12-31 10:21:55')
2529+
);
2530+
2531+
ANALYZE TABLE t1;
2532+
SET TIMESTAMP=UNIX_TIMESTAMP('2019-03-11 12:00:00');
2533+
EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'1976-11-31');
2534+
SET TIMESTAMP=UNIX_TIMESTAMP('1975-03-11 12:00:00');
2535+
EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'2000-11-31');
2536+
2537+
SET TIMESTAMP=DEFAULT;
2538+
DROP TABLE t1;
2539+
2540+
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER)
2541+
PARTITION BY RANGE (a)
2542+
(
2543+
PARTITION p1 VALUES LESS THAN (10),
2544+
PARTITION p2 VALUES LESS THAN MAXVALUE
2545+
);
2546+
2547+
ANALYZE TABLE t1;
2548+
2549+
set @a=1,@b=22;
2550+
EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b);
2551+
EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2);
2552+
2553+
set @a=11,@b=22;
2554+
EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b);
2555+
EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2);
2556+
2557+
PREPARE s from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,?)";
2558+
set @a=1,@b=22;
2559+
EXECUTE s USING @a,@b;
2560+
2561+
set @a=11,@b=22;
2562+
EXECUTE s USING @a,@b;
2563+
2564+
PREPARE p from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,1), (?,2)";
2565+
set @a=1,@b=22;
2566+
EXECUTE p USING @a,@b;
2567+
2568+
set @a=11,@b=22;
2569+
EXECUTE p USING @a,@b;
2570+
2571+
DROP TABLE t1;
2572+
2573+
CREATE TABLE t1 (
2574+
id INT PRIMARY KEY,
2575+
f1 FLOAT
2576+
)
2577+
PARTITION BY RANGE (id)
2578+
(
2579+
PARTITION p0 VALUES LESS THAN (10),
2580+
PARTITION p1 VALUES LESS THAN MAXVALUE
2581+
);
2582+
2583+
ANALYZE TABLE t1;
2584+
2585+
EXPLAIN INSERT INTO t1 (id, f1) VALUES (1,RAND());
2586+
EXPLAIN INSERT INTO t1 VALUES (20,RAND());
2587+
2588+
DROP TABLE t1;

sql/partition_info.cc

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ bool partition_info::can_prune_insert(
459459
@param info COPY_INFO used for default values handling
460460
@param copy_default_values True if we should copy default values
461461
@param used_partitions Bitmap to set
462+
@param tables_locked True if tables are locked
462463
463464
@returns Operational status
464465
@retval false Success
@@ -467,20 +468,41 @@ bool partition_info::can_prune_insert(
467468
so caller must check thd->is_error().
468469
*/
469470

470-
bool partition_info::set_used_partition(THD *thd,
471-
const mem_root_deque<Item *> &fields,
472-
const mem_root_deque<Item *> &values,
473-
COPY_INFO &info,
474-
bool copy_default_values,
475-
MY_BITMAP *used_partitions) {
471+
bool partition_info::set_used_partition(
472+
THD *thd, const mem_root_deque<Item *> &fields,
473+
const mem_root_deque<Item *> &values, COPY_INFO &info,
474+
bool copy_default_values, MY_BITMAP *used_partitions, bool tables_locked) {
476475
uint32 part_id;
477476
longlong func_value;
478477

479478
assert(thd);
480479

481-
/* Only allow checking of constant values */
482-
for (Item *item : values) {
483-
if (!item->const_item()) return true;
480+
/*
481+
In prepare phase, allow partition pruning from constant values.
482+
In execution phase, allow partition pruning for values that are
483+
const-for-execution.
484+
*/
485+
if (!fields.empty()) {
486+
auto value_it = values.begin();
487+
for (Item *fld : fields) {
488+
Item *value = *value_it++;
489+
Item_field *field = fld->field_for_view_update();
490+
if (bitmap_is_set(&full_part_field_set, field->field->field_index())) {
491+
if (!(value->const_item() ||
492+
(tables_locked && value->const_for_execution())))
493+
return true;
494+
}
495+
}
496+
} else {
497+
Field *field = nullptr;
498+
for (Item *value : values) {
499+
field = *table->field++;
500+
if (bitmap_is_set(&full_part_field_set, field->field_index())) {
501+
if (!(value->const_item() ||
502+
(tables_locked && value->const_for_execution())))
503+
return true;
504+
}
505+
}
484506
}
485507

486508
if (copy_default_values) restore_record(table, s->default_values);

sql/partition_info.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,8 @@ class partition_info {
511511
void report_part_expr_error(bool use_subpart_expr);
512512
bool set_used_partition(THD *thd, const mem_root_deque<Item *> &fields,
513513
const mem_root_deque<Item *> &values, COPY_INFO &info,
514-
bool copy_default_values, MY_BITMAP *used_partitions);
514+
bool copy_default_values, MY_BITMAP *used_partitions,
515+
bool tables_locked);
515516
/**
516517
PRUNE_NO - Unable to prune.
517518
PRUNE_DEFAULTS - Partitioning field is only set to

0 commit comments

Comments
 (0)