Mysql中unionall的max下推案例

2022-05-12 09:50:06 浏览数 (1)

长求总 max …(union all)中max无法自动下推,要跟库业务场景手动下推。 改造为 Max…(union all max…union all…max…)

1 构造测试数据

代码语言:javascript复制
/home/mingjie.gmj/bin/sysbench-1.0.16/bin/sysbench oltp_common --threads=64 --events=0 --mysql-socket=xxx --mysql-user=xxx --mysql-db=xxx --tables=2 --table_size=2000000  prepare

select count(*) from sbtest1;
 ---------- 
| count(*) |
 ---------- 
|  2000000 |
 ---------- 

CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=2000001 DEFAULT CHARSET=utf8mb4;

2 问题复现

代码语言:javascript复制
select count(*) from sbtest1 where k<1000000;
 ---------- 
| count(*) |
 ---------- 
|   750243 |
 ---------- 
explain select count(*) from sbtest1 where k<1000000;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: sbtest1
   partitions: NULL
         type: range
possible_keys: k_1
          key: k_1
      key_len: 4
          ref: NULL
         rows: 960984
     filtered: 100.00
        Extra: Using where; Using index

union的一个条件返回大量数据

代码语言:javascript复制
explain select max(un.m) from
(select k as m from sbtest1 where k<1000000
union all
select k as m from sbtest2 where k=1000000) un;
 ---- ------------- ------------ ------------ ------- --------------- ------ --------- ------- -------- ---------- -------------------------- 
| id | select_type | table      | partitions | type  | possible_keys | key  | key_len | ref   | rows   | filtered | Extra                    |
 ---- ------------- ------------ ------------ ------- --------------- ------ --------- ------- -------- ---------- -------------------------- 
|  1 | PRIMARY     | <derived2> | NULL       | ALL   | NULL          | NULL | NULL    | NULL  | 961088 |   100.00 | NULL                     |
|  2 | DERIVED     | sbtest1    | NULL       | range | k_1           | k_1  | 4       | NULL  | 960984 |   100.00 | Using where; Using index |
|  3 | UNION       | sbtest2    | NULL       | ref   | k_2           | k_2  | 4       | const |    104 |   100.00 | Using index              |
 ---- ------------- ------------ ------------ ------- --------------- ------ --------- ------- -------- ---------- -------------------------- 

0.32649700s

优化

手动下推max

代码语言:javascript复制
explain select max(un.m) from
(select max(k) as m from sbtest1 where k<1000000
union all
select max(k) as m from sbtest2 where k=1000000) un;
 ---- ------------- ------------ ------------ ------ --------------- ------ --------- ------ ------ ---------- ------------------------------ 
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                        |
 ---- ------------- ------------ ------------ ------ --------------- ------ --------- ------ ------ ---------- ------------------------------ 
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | NULL                         |
|  2 | DERIVED     | NULL       | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Select tables optimized away |
|  3 | UNION       | NULL       | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Select tables optimized away |
 ---- ------------- ------------ ------------ ------ --------------- ------ --------- ------ ------ ---------- ------------------------------ 

0.00045525s

结果

执行时间从0.32649700s

提升到0.00045525s

提升2195倍

0 人点赞