Bootstrap

mysql视图建立MERGE算法和TEMPTABLE算法的区别(效率与表锁定问题)

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通常更有效,而且如果使用了临时表,视图是不可更新的。
;