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通常更有效,而且如果使用了臨時表,視圖是不可更新的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章