创建视图可选的ALGORITHM子句对视图重写优化的影响

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

视图可选的ALGORITHM子句
测试版本:
percona server 5.6.19-67.0-log Percona Server (GPL), Release 67.0, Revision 618

该选项是Mysql扩展的SQL标准,影响mysql怎样处理视图,可以有三个值:MERGE,TEMPTABLE,UNDEFINED,默认是UNDEFINED。
总结:
视图能被mysql进行重写优化,需要满足一些条件,同时在定义时,不能使用TEMPTABLE算法

MERGE:
合并视图定义到相应的查询语句(视图重写)。

TEMPTABLE:
从视图检索的结果集存放到临时表,然后执行查询语句(影响视图重写)。

UNDEFINED:
mysql选择使用哪个算法,优先MERGE,通常更有效,如果使用临时表,视图不能更新,但是使用TEMPTABLE可以提前释放对基表的锁

如:
创建基本表:
Create Table: CREATE TABLE `t` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  `c3` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

使用MERGE算法创建简单视图:
root@[test1] 12:29:50>CREATE ALGORITHM = MERGE VIEW v_merge (vc1, vc2) AS SELECT c1, c2 FROM t WHERE c3 > 100;
Query OK, 0 rows affected (0.00 sec)

root@[test1] 12:30:00>explain extended SELECT * FROM v_merge;
+----+-------------+-------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t     | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

查看优化后的语句:视图已经重写为基本表t,并将视图的where条件应用到查询语句
root@[test1] 12:30:21>show warnings;
+-------+------+---------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                   |
+-------+------+---------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `test1`.`t`.`c1` AS `vc1`,`test1`.`t`.`c2` AS `vc2` from `test1`.`t` where (`test1`.`t`.`c3` > 100) |
+-------+------+---------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

使用TEMPTABLE算法创建同上面定义的视图:
root@[test1] 12:30:26>CREATE ALGORITHM = TEMPTABLE VIEW v_temptable (vc1, vc2) AS SELECT c1, c2 FROM t WHERE c3 > 100;
Query OK, 0 rows affected (0.00 sec)

查询计划:使用了衍生表,也就是先执行视图定义,然后将结果集用于执行查询语句
root@[test1] 12:31:08>explain extended SELECT * FROM v_temptable;
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | NULL        |
|  2 | DERIVED     | t          | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

查看优化后的语句:视图名没有去掉,没有将简单查询进行重写为对基表的查询
root@[test1] 12:31:17>show warnings;
+-------+------+------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                    |
+-------+------+------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `v_temptable`.`vc1` AS `vc1`,`v_temptable`.`vc2` AS `vc2` from `test1`.`v_temptable` |
+-------+------+------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

使用UNDEFINED的情况:
1、没有使用ALGORITHM子句;
2、使用明确的ALGORITHM=UNDEFINED定义;
3、ALGORITHM=MERGE,如果含有一些特殊结构,Mysql生成一个警告,并设置算法为UNDEFINED;

如果视图包含下面的结构,不能使用MERGE:
1、聚合函数(SUM(),MIN(),MAX(),COUNT()等)
2、DISTINCT;
3、GROUP BY;
4、HAVING
5、LIMIT
6、UNION或UNION ALL
7、子查询在select列
8、参考仅仅文字值,没有潜在表

如:
1、视图包含聚合函数:
root@[test1] 15:22:25>CREATE ALGORITHM = MERGE VIEW v_merge_sum (vc1) AS SELECT sum(c1) FROM t WHERE c3 > 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

查看警告可以得到使用undefined算法,不能使用merge算法
root@[test1] 15:22:41>show warnings;
+---------+------+-------------------------------------------------------------------------------+
| Level   | Code | Message                                                                       |
+---------+------+-------------------------------------------------------------------------------+
| Warning | 1354 | View merge algorithm can't be used here for now (assumed undefined algorithm) |
+---------+------+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)

查看视图定义:使用UNDEFINED算法
root@[test1] 14:56:26>show create table v_merge_sum\G;
*************************** 1. row ***************************
                View: v_merge_sum
         Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_merge_sum` AS select sum(`t`.`c1`) AS `vc1` from `t` where (`t`.`c3` > 1)
character_set_client: gbk
collation_connection: gbk_chinese_ci
1 row in set (0.00 sec)

ERROR: 
No query specified

对视图进行简单查询:使用了衍生表,但是视图名没有出现
root@[test1] 15:23:05>explain extended select * from v_merge_sum;
+----+-------------+------------+--------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table      | type   | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------+--------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | | system | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL        |
|  2 | DERIVED     | t          | ALL    | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+------------+--------+---------------+------+---------+------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

root@[test1] 15:23:17>show warnings;
+-------+------+----------------------------------------------+
| Level | Code | Message                                      |
+-------+------+----------------------------------------------+
| Note  | 1003 | /* select#1 */ select '6' AS `vc1` from dual |
+-------+------+----------------------------------------------+
1 row in set (0.00 sec)

2、视图包含distinct:
root@[test1] 15:25:05>CREATE ALGORITHM = MERGE VIEW v_merge_distinct (vc1,vc2) AS SELECT distinct c1,c2 FROM t WHERE c3 > 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

查看警告可以得到使用undefined算法,不能使用merge算法
root@[test1] 15:25:20>show warnings;
+---------+------+-------------------------------------------------------------------------------+
| Level   | Code | Message                                                                       |
+---------+------+-------------------------------------------------------------------------------+
| Warning | 1354 | View merge algorithm can't be used here for now (assumed undefined algorithm) |
+---------+------+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)

查询计划:使用了衍生表,视图没有重写
root@[test1] 15:25:24>explain extended select * from v_merge_distinct;
+----+-------------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                        |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
|  1 | PRIMARY     | | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL                         |
|  2 | DERIVED     | t          | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where; Using temporary |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test1] 15:26:13>show warnings;
+-------+------+---------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                   |
+-------+------+---------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `v_merge_distinct`.`vc1` AS `vc1`,`v_merge_distinct`.`vc2` AS `vc2` from `test1`.`v_merge_distinct` |
+-------+------+---------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

3、视图包含group by子句:不是使用MERGE算法
root@[test1] 15:30:58>CREATE ALGORITHM = MERGE VIEW v_merge_groupby (vc1,vc2) AS SELECT c1,c2 FROM t group by c3;
Query OK, 0 rows affected, 1 warning (0.12 sec)

root@[test1] 15:31:44>show warnings;
+---------+------+-------------------------------------------------------------------------------+
| Level   | Code | Message                                                                       |
+---------+------+-------------------------------------------------------------------------------+
| Warning | 1354 | View merge algorithm can't be used here for now (assumed undefined algorithm) |
+---------+------+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)

查看简单查询的查看计划:使用衍生表,使用临时表进行排序,视图没有消除
root@[test1] 15:31:48>explain extended select * from v_merge_groupby;
+----+-------------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                           |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
|  1 | PRIMARY     | | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL                            |
|  2 | DERIVED     | t          | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using temporary; Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test1] 15:33:02>show warnings;
+-------+------+------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                |
+-------+------+------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `v_merge_groupby`.`vc1` AS `vc1`,`v_merge_groupby`.`vc2` AS `vc2` from `test1`.`v_merge_groupby` |
+-------+------+------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

4、视图含limit条件:不能使用MERGE算法
root@[test1] 15:35:02>CREATE ALGORITHM = MERGE VIEW v_merge_limit (vc1,vc2) AS SELECT c1,c2 FROM t where c3>2 limit 10;
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@[test1] 15:35:39>show warnings;
+---------+------+-------------------------------------------------------------------------------+
| Level   | Code | Message                                                                       |
+---------+------+-------------------------------------------------------------------------------+
| Warning | 1354 | View merge algorithm can't be used here for now (assumed undefined algorithm) |
+---------+------+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)

简单查询的查询计划:使用衍生表,视图没有重写成基表
root@[test1] 15:35:41>explain extended select * from v_merge_limit;
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL        |
|  2 | DERIVED     | t          | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

root@[test1] 15:35:54>show warnings;
+-------+------+------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                          |
+-------+------+------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `v_merge_limit`.`vc1` AS `vc1`,`v_merge_limit`.`vc2` AS `vc2` from `test1`.`v_merge_limit` |
+-------+------+------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

5、子查询在目标列:不能使用使用MERGE算法
root@[test1] 15:45:43>CREATE ALGORITHM = MERGE VIEW v_merge_select (vc1,vc2) AS SELECT c1,(select c2 from t where c1=1) FROM t where c3>2;
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@[test1] 15:45:49>show warnings;
+---------+------+-------------------------------------------------------------------------------+
| Level   | Code | Message                                                                       |
+---------+------+-------------------------------------------------------------------------------+
| Warning | 1354 | View merge algorithm can't be used here for now (assumed undefined algorithm) |
+---------+------+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)

简单查询的查询计划:使用衍生表,视图没有重写成基表
root@[test1] 15:45:53>explain extended select * from v_merge_select;
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL        |
|  2 | DERIVED     | t          | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
|  3 | SUBQUERY    | t          | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)

root@[test1] 15:46:10>show warnings;
+-------+------+---------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                             |
+-------+------+---------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `v_merge_select`.`vc1` AS `vc1`,`v_merge_select`.`vc2` AS `vc2` from `test1`.`v_merge_select` |
+-------+------+---------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

6、视图含UNION
root@[test1] 15:52:48>CREATE ALGORITHM = MERGE VIEW v_merge_union AS SELECT c1,c2 FROM t where c3>2 union select b1,b2 from a;
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@[test1] 15:56:11>show warnings;
+---------+------+-------------------------------------------------------------------------------+
| Level   | Code | Message                                                                       |
+---------+------+-------------------------------------------------------------------------------+
| Warning | 1354 | View merge algorithm can't be used here for now (assumed undefined algorithm) |
+---------+------+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)

简单查询的查询计划:使用衍生表,视图没有重写成基表
root@[test1] 15:56:15>explain extended select * from v_merge_union;
+----+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type  | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | PRIMARY      | | ALL  | NULL          | NULL | NULL    | NULL |    6 |   100.00 | NULL            |
|  2 | DERIVED      | t          | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where     |
|  3 | UNION        | a          | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL            |
| NULL | UNION RESULT | | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
+----+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
4 rows in set, 1 warning (0.00 sec)

root@[test1] 15:56:32>show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                      |
+-------+------+--------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `v_merge_union`.`c1` AS `c1`,`v_merge_union`.`c2` AS `c2` from `test1`.`v_merge_union` |
+-------+------+--------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)




来自为知笔记(Wiz)


转载于:https://my.oschina.net/anthonyyau/blog/298967

你可能感兴趣的:(创建视图可选的ALGORITHM子句对视图重写优化的影响)