mysql视图建立MERGE算法和TEMPTABLE算法的区别(效率与表锁定问题)
视图创建语句:
-
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
-
可选的ALGORITHM子句是对标准SQL的MySQL扩展。ALGORITHM可取三个值:MERGE、TEMPTABLE或UNDEFINED。如果没有ALGORITHM子句,默认算法是UNDEFINED(未定义的)。算法会影响MySQL处理视图的方式。
MERGE算法
-
文档解释:
-
对于MERGE,会将引用视图的语句的文本与视图定义合并起来,使得视图定义的某一部分取代语句的对应部分
-
通俗的说,意思就是MERGE算法是一个合并算法,每当执行的时候,先将视图的sql语句与外部查询视图的sql语句,合并在一起,最终执行;这样操作对效率基本上没有什么影响,但是使用这种算法有一定限制,以下引自文档:
-
MERGE算法要求视图中的行和基表中的行具有一对一的关系。如果不具有该关系。必须使用临时表取而代之。如果视图包含下述结构中的任何一种,将失去一对一的关系: · 聚合函数(SUM(), MIN(), MAX(), COUNT()等)。 · DISTINCT · GROUP BY · HAVING · UNION或UNION ALL · 仅引用文字值(在该情况下,没有基本表)。
-
举个例子
-
/** 定义两张表 seller_sku表包括以下字段:id(主键),seller_id(门店ID),sku_id(商品sku的id,对应goods_sku的id),amount(商品的库存) goods_sku 表包括以下字段:id(主键),goods_name(sku的名称) **/ #案例1 查询商品库存大于50的门店的商品所对应的成本 CREATE OR REPLACE VIEW amount_50_sku AS SELECT seller_id, price, sku_id, amount, (price*amount) AS sku_values FROM sellers_sku WHERE amount > 50 #方法A SELECT * FROM amount_50_sku #方法B SELECT seller_id,price,sku_id,amount,(price*amount) AS sku_values FROM sellers_sku
-
方法A和方法B查询出结果的时间是差不多的,MERGE算法对效率的影响很小。
TEMPTABLE算法
-
文档解释
-
对于TEMPTABLE,视图的结果将被置于临时表中,然后使用它执行语句。
-
TEMPTABLE算法是将结果放置到临时表中,意味这要mysql要先创建好一个临时表,然后将结果放到临时表中去,然后再使用这个临时表进行相应的查询。为什么文档中说“果使用了临时表,视图是不可更新的。”就是因为这个算法生成的视图其实就是一个结果的临时表,是无法执行update语句的,mysql会报错:
-
“错误代码: 1288 The target table seller_sku_amount of the UPDATE is not updatable"
-
最最重要的是,TEMPTABLE算法会创建临时表,这个过程是会影响效率的,如以下案例:
-
/** seller_sku表包括以下字段:id(主键),seller_id(门店ID),sku_id(商品sku的id,对应goods_sku的id),amount(商品的库存) goods_sku 表包括以下字段:id(主键),goods_name(sku的名称) **/ #案例2 显示每个商品各个门店库存的总和 #创建视图 CREATE OR REPLACE VIEW seller_sku_amount AS SELECT sku_id, SUM(amount) AS amount_total FROM sellers_sku GROUP BY sku_id #使用视图查询 SELECT seller_sku_amount.sku_id, seller_sku_amount.amount_total, goods_sku.* FROM seller_sku_amount JOIN goods_sku ON goods_sku.`id` = seller_sku_amount.`sku_id` #原生SQL查询 SELECT sellers_sku.sku_id, SUM(sellers_sku.amount) AS amount_total, goods_sku.* FROM sellers_sku JOIN goods_sku ON sellers_sku.`sku_id` = goods_sku.`id` GROUP BY sku_id ORDER BY amount_total DESC
-
以上两个查询,使用视图查询的速度为比使用原生SQL查询的效率慢50%,随着数据量的增大,这个效率还会更慢(数据量越大,需要往临时表填充更多的数据);
但是TEMPTABLE算法也不是没有好处的,TEMPTABLE算法创建临时表之后、并在完成语句处理之前,能够释放基表上的锁定。与MERGE算法相比,锁定释放的速度更快,这样,使用视图的其他客户端不会被屏蔽过长时间。
UNDEFINED算法
- UNDEFINED算法没啥好区分的,直接引用文档的:
- 对于UNDEFINED,MySQL将选择所要使用的算法。如果可能,它倾向于MERGE而不是TEMPTABLE,这是因为MERGE通常更有效,而且如果使用了临时表,视图是不可更新的。