天天看點

【資料庫優化專題】MySQL視圖優化(二)

本期繼續為大家帶來mysql視圖優化的原創專家文章分享,來自dba+社群mysql領域原創專家——李海翔。以下是銜接上周所釋出的第二部分的内容,未完部分敬請繼續關注後續更新。

專家簡介

【資料庫優化專題】MySQL視圖優化(二)

李海翔

網名:那海藍藍

dba+社群mysql領域原創專家

從事資料庫研發、資料庫測試與技術管理等工作10餘年,對資料庫的核心有深入研究,擅長于postgresql和mysql等開源資料庫的核心與架構。現任職于oracle公司mysql全球開發團隊,從事查詢優化技術的研究和mysql查詢優化器的開發工作。著有《資料庫查詢優化器的藝術》一書。

二、mysql視圖優化方式

測試用例:

建立2張表,建立一個簡單視圖、一個複雜視圖、一個使用unoion操作的視圖,并插入少量資料。

【資料庫優化專題】MySQL視圖優化(二)

1 v5.6之前的版本

以v5.5為例,mysql對于視圖的處理,盡在mysql_make_view()這樣的一個函數中完成。

1.1 對于 v_union這樣的視圖,mysql文法分析階段後期調用mysql_parse()首先解決視圖展開的處理,對于可以展開的視圖(即可以采用上拉技術進行扁平化處理),通過調用open_and_lock_tables()->open_table()并調用open_new_frm()讀取視圖的定義。

1.2 然後,調用mysql_make_view()完成對于視圖的文法分析,并對可以merge(即可把視圖進行上拉優化,上拉的相關思路/原理,可參見:《mysql子查詢優化---詳解--1》, http://blog.163.com/li_hx/blog/static/18399141320150253652874/)的視圖定義體中的查詢語句進行merge操作(表對象上拉到父層,where條件合并到上層)。是以,在5.5版本,對于視圖的優化,盡在mysql_make_view()這個函數中。

1.3 間接地,可以側面地對于q1(http://blog.163.com/li_hx/blog/static/18399141320158220574035/)問題得出一個結論:mysql v5.5對于視圖和派生表的處理方式“可能不一樣”。

1.4 可以merge的條件

不是所有的視圖都是可以執行“視圖重寫”優化的。這點可以參考“《資料庫查詢優化器的藝術》一書第28頁2.2.2視圖重寫”一節。

mysql v5.5對于可merge的視圖的條件是:

1)視圖建立時,沒有指定 view_algorithm_tmptable,即視圖不使用臨時表

2)視圖定義中不帶有group/having/distinct/limit/聚集函數等子句

從第2條的條件看,這相當于在說:mysql不支援對複雜視圖進行優化。

1.5 對于派生表的處理方式

首先,看如下的事例:

【資料庫優化專題】MySQL視圖優化(二)

這是一個簡單的2表連接配接,mysql v5.5把tt這個派生表單獨處理,然後再與t1進行連接配接。即不能直接進行t1 和t2表的連接配接操作,這樣,t1外表驅動了一個物化了的表,sql的運作效率低下。這個簡單事例,足以證明mysql早期版本的優化器是何等的弱,為人诟病确也正常。

1.6 mysql中派生表與sql标準的差異

mysql的查詢執行計劃對于 select_type列中的derived解釋如下:

derived : derived table select (subquery in from clause)

這表明derived是一個源自from子句的查詢。而sql标準并沒有把derived table限定到from子句中,注意這二者之間的差别(意味着mysql在這點上沒有完全遵循sql标準,^_^)。

例如,對于mysql,可以通過如下執行個體來驗證mysql對于derived定義的局限性。

【資料庫優化專題】MySQL視圖優化(二)

在如上的查詢執行計劃中,(select a2 from t2)被當作了子查詢而不是derived table。

未完待續……敬請持續關注~

<b>本文來自雲栖社群合作夥伴"dbaplus",原文釋出時間:2015-11-12</b>