MySQL查詢優化器源碼分析

目的

基于之前出現的主從庫分別執行相同語句,查詢計劃和執行時間不同的問題。通過對源代碼跟蹤和調試,對MySQL的查詢優化器進行分析並編寫文檔,爲開發人員和數據庫管理人員提供查詢SQL語句的建議。

 

基礎

MySQL的設計架構在官方文檔中給出,如下圖所示。該圖的具體描述和講解,請參考官方文檔或地址:http://dev.mysql.com/doc/refman/5.1/en/pluggable-storage-overview.html

 

 MySQL查詢優化器源碼分析

圖中Optimizer部分爲本文研究的重點,主要對Parser解析之後的SQL,根據統計的數據,對訪問代價進行權衡,制定執行計劃。查詢優化器是MySQL中比較活躍的一部分,代碼會經常變動。但整體而言,對查詢優化器整體把握和理解之後,其他的版本也基本可以輕松理解。以下內容將通過對MySQL 5.5.20版本的源碼進行分析,供大家參考。

 

代碼分析

| | | | >handle_select

| | | | | >mysql_select/mysql_union

| | | | | | >JOIN::prepare

| | | | | | | >setup_tables

| | | | | | | <setup_tables

| | | | | | | >setup_fields

| | | | | | | <setup_fields

| | | | | | | >setup_without_group

| | | | | | | | >setup_conds

| | | | | | | | <setup_conds

| | | | | | | | >setup_order

| | | | | | | | <setup_order

| | | | | | | | >setup_group

| | | | | | | | <setup_group

| | | | | | | <setup_without_group

| | | | | | | >setup_procedure

| | | | | | | <setup_procedure

| | | | | | <JOIN::prepare

| | | | | | >JOIN::optimize

| | | | | | | >simplify_joins

| | | | | | | <simplify_joins

| | | | | | | >build_bitmap_for_nested_joins

| | | | | | | <build_bitmap_for_nested_joins

| | | | | | | >optimize_cond

| | | | | | | <optimize_cond

| | | | | | | >prune_partitions

| | | | | | | <prune_partitions

| | | | | | | >make_join_statistics

| | | | | | | | >make_select

| | | | | | | | <make_select

| | | | | | | | >get_quick_record_count

| | | | | | | | | >SQL_SELECT::test_quick_select

| | | | | | | | | | >get_mm_tree

| | | | | | | | | | <get_mm_tree

| | | | | | | | | | >get_best_group_min_max

| | | | | | | | | | <get_best_group_min_max

| | | | | | | | | | >get_key_scans_params

| | | | | | | | | | <get_key_scans_params

| | | | | | | | | | >get_best_ror_intersect

| | | | | | | | | | <get_best_ror_intersect

| | | | | | | | | | >get_best_disjunct_quick

| | | | | | | | | | <get_best_disjunct_quick

| | | | | | | | | | >TRP_RANGE::make_quick

| | | | | | | | | | <TRP_RANGE::make_quick

| | | | | | | | | <SQL_SELECT::test_quick_select

| | | | | | | | <get_quick_record_count

| | | | | | | | >choose_plan

| | | | | | | | | >optimize_straight_join

| | | | | | | | | | >best_access_path

| | | | | | | | | | <best_access_path

| | | | | | | | | <optimize_straight_join

| | | | | | | | | >greedy_search

| | | | | | | | | | >best_extension_by_limited_search

| | | | | | | | | | | >best_access_path

| | | | | | | | | | | <best_access_path

| | | | | | | | | | <best_extension_by_limited_search

| | | | | | | | | <greedy_search

| | | | | | | | <choose_plan

| | | | | | | <make_join_statistics

| | | | | | | >get_best_combination

| | | | | | | <get_best_combination

| | | | | | | >make_join_select

| | | | | | | <make_join_select

| | | | | | <JOIN::optimize

| | | | | | >JOIN::exec

| | | | | | | >do_select

| | | | | | | <do_select

| | | | | | <JOIN::exec

| | | | | | >st_select_lex::cleanup()

| | | | | | <st_select_lex::cleanup()

| | | | | <mysql_select/mysql_union

| | | | <handle_select

 

2.2 Optimizer流程圖

         通過以上的函數調用層次,對optimizer的處理流程圖形化,方便清晰的理解和查看具體的流程。

由于函數調用層次不利于清晰的顯示處理流程,因此以下流程圖摒棄了調用層次的界限,更關注邏輯處理。

 

MySQL查詢優化器源碼分析

 

2.3 函數詳細介紹

1) handle_select()(sql/sql_select.cc265)

handle_select()函數用于執行查詢操作。該函數對Union進行了判斷,如果查詢SQL中不包含union關鍵字,函數直接執行mysql_select()函數處理;否則,將執行mysql_union()函數。

2) mysql_select()/mysql_union()(sql/sql_select.cc2498|sql/sql_union.cc31)

         mysql_select()函數是單個select查詢的“入口函數”。該函數執行SQL優化的一些列操作。區別于mysql_select()函數,mysql_union()函數逐個執行union中單個select查詢優化的一系列操作。執行SQL優化的過程調用相同的函數實現,僅在執行前期的處理過程不一致。

3) JOIN::prepare()(sql/sql_select.cc499)

         JOIN::prepare()函數用于爲整個查詢做准備工作。其中包括准備表、檢查表是否可以訪問、檢查字段、檢查非group函數、准備procedure等工作。以下是該過程調用的重要函數,具體查看回應函數的解釋。

該函數簡化後,並且忽略函數調用層次的流程圖如下圖所示:

 

MySQL查詢優化器源碼分析

 

4) setup_tables()(sql/sql_base.cc7963)

         setup_tables()函數用于准備查詢所需要的所有表。該函數被setup_tables_and_check_access()函數(sql/sql_base.cc8058)調用,而setup_tables_and_check_access()函數用于准備表以及檢查表的是否可以訪問,在JOIN::prepare()函數中被調用,而該函數分別調用setup_tables()check_single_table_access(),其中後者對所有需要的表,循環進行檢查是否可以訪問。

5) setup_fields()(sql/sql_base.cc7825)

setup_fields()函數用于檢查所有給定字段是否存在。該函數檢查所有查詢中給定的數據表的字段,對數據表的列進行查找。其中調用了更深層次的函數,如下所示:find_field_in_tables() -> find_field_in_table_ref() -> find_field_in_table()。其中find_field_in_tables()根據查詢的表,循環調用find_field_in_table_ref()函數。

6) setup_without_group()(sql/sql_select.cc446)

         setup_without_group()函數用于准備非group函數。該函數是一個內嵌函數,但是該函數的邏輯並不簡單。該函數調用了setup_conds()setup_order()setup_group()函數,具體的函數解釋見下面內容。

7) setup_conds()(sql/sql_base.cc8379)

setup_conds()函數用于准備SQL查詢中where的所有條件。該函數對where中給定的條件,檢查對應數據表的字段。其中調用了find_field_in_table_ref()函數,用于檢查數據表中的字段。

8)setup_order()(sql/sql_select.cc14996)

         setup_order()函數用于准備SQL查詢中order by的條件。該函數對每個order by字段都調用了find_order_in_list()函數,而find_order_in_list()用于處理group byorder by的字段。

9)setup_group()(sql/sql_select.cc15037)

         setup_group()函數用于初始化SQL查詢中group by的條件。該函數同setup_order()的處理邏輯類似,不在贅述。

10) setup_procedure()(sql/procedure.cc80)

         setup_procedure()函數用于准備procedure處理。

注意:除以上函數調用外,JOIN::prepare()過程中如果存在order bygroup by的條件時,在調用以上函數之後,還有一系列操作,比如分配額外的隱藏字段、分離sum結果和item樹等內容。

11) JOIN::optimize()(sql/sql_select.cc854)

         JOIN::optimize()是整個查詢優化器的核心內容。查詢優化主要對Join進行簡化、優化where條件、優化having條件、裁剪分區partition(如果查詢的表是分區表)、優化count()/min()/max()聚集函數、統計join的代價、搜索最優的join順序、生成執行計劃、執行基本的查詢、優化多個等式謂詞、執行join查詢、優化distinct、創建臨時表存儲臨時結果等操作。以下將對該過程調用的重要函數,進行詳細的講解。

該函數簡化後的流程圖如下圖所示:

 

MySQL查詢優化器源碼分析

 

12) simplify_joins()(sql/sql_select.cc8940)

simplify_joins()函數簡化join操作。該函數將可以用內連接替換的外連接進行替換,並對嵌套join使用的表、非null表、依賴表等進行計算。該函數的實現是一個遞歸過程,在遞歸中,所有的特征將被計算,所有可以被替換的外連接被替換,所有不需要的括號也被去掉。此外,該函數前的注釋中,給出了多個例子,用于解釋外連接替換爲內連接的一些特征。

 

Sample 1:

  SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a WHERE t2.b < 5

==>

SELECT * FROM t1 INNER JOIN t2 ON t2.a=t1.a WHERE t2.b < 5

==>

SELECT * FROM t1, t2 ON t2.a=t1.a WHERE t2.b < 5 AND t2.a=t1.a

Sample 2:

SELECT * from t1 LEFT JOIN (t2, t3) ON t2.a=t1.a t3.b=t1.b WHERE t2.c < 5

==>

SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a t3.b=t1.b

Sample 3:

SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a LEFT JOIN t3 ON t3.b=t2.b WHERE t3 IS NOT NULL

==>

  SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a, t3 WHERE t3 IS NOT NULL AND t3.b=t2.b

==>

  SELECT * FROM t1, t2, t3 WHERE t3 IS NOT NULL AND t3.b=t2.b AND t2.a=t1.a

 

13) build_bitmap_for_nested_joins()(sql/sql_select.cc9135)

         build_bitmap_for_nested_joins()函數爲每個嵌套joinbitmap中分配一位。該函數也是一個遞歸過程,返回第一個沒有使用的bit

14) optimize_cond()(sql/sql_select.cc9405)

optimize_cond()函數分別對where條件和having條件建立多個等價謂詞,並且刪除可以被推導出的等價謂詞。該函數調用build_equal_items()函數(sql/sql_select.cc8273)用于該處理過程,該函數是一個遞歸過程,並在函數前,列舉了多個實例,供參考和理解。

 

Sample 1:

SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t2.a=t4.a WHERE t1.a=t2.a;

==>

SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON multiple equality (t1.a,t2.a,t3.a,t4.a)

Sample 2:

SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a WHERE t1.a=t2.a

==>

SELECT * FROM (t1 LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a),t2 WHERE t1.a=t2.a

Sample 3:

SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t2.a=t4.a AND t3.a=t4.a WHERE t1.a=t2.a

==>

SELECT * FROM (t2 LEFT JOIN (t3,t4)ON t2.a=t4.a AND t3.a=t4.a), t1 WHERE t1.a=t2.a        

 

此外,該函數調用propagate_cond_constants()函數(sql/sql_select.cc8763),用于處理(a=b and b=1)爲(a=1 and b=1)操作,該函數也是一個遞歸過程。調用remove_eq_conds()函數(sql/sql_select()9617),用于刪除(a=a以及1=11=2)條件,該函數調用了internal_remove_eq_conds()遞歸處理函數(sql_select.cc9462)

15) prune_partitions()(sql/opt_range.cc2611)

prune_partitions()函數通過分析查詢條件,查找需要的數據分區。該函數僅對分區表有效,普通的表不做處理。

16) make_join_statistics()(sql/sql_select.cc2651)

         make_join_statistics()函數用于計算最好的join執行計劃。該過程較複雜,分爲以下幾個步驟:

首先如果join是外連接,利用FloydWarshall(弗洛伊德)算法建立傳遞閉包依賴關系,該過程較複雜,具體參考該算法的一些內容。

之後進行主鍵或唯一索引的常量查詢處理,該過程是一個循環過程,與執行計劃中的ref類型有關。

接下來,計算每個表中匹配的行數以及掃描的時間,該過程得到的結果是估計的值,並非實際查詢需要的記錄數和時間。並且調用了一下的make_select()函數和get_quick_recond_count()函數,具體內容參照以下相應函數的分析。該過程從生成執行計劃來看,與indexfull類型有關。

最後,根據以上統計的記錄數和時間,選擇一個最優的join順序。實際該處理邏輯,調用choose_plan()函數處理,參照以下choose_plan()函數分析。

該函數簡化後的流程圖如下圖所示:

 

MySQL查詢優化器源碼分析

 

17) make_select()(sql/opt_range.cc1067)

make_select()函數是普通查詢和快速範圍查詢處理的函數。該函數通過計算查詢記錄在cache中的偏移量除以ref長度的商,得到查詢的行數。如果cache中沒有緩存,那麽退出該過程,執行get_quick_record_count()函數處理過程。

18) get_quick_record_count()(sql/sql_select.cc2602)

get_quick_record_count()函數用于估計查詢需要每個表的記錄數。該過程調用SQL_SELECT::test_quick_select()函數用于具體的處理邏輯,具體見以下函數的詳細分析過程。

19) SQL_SELECT::test_quick_select()(sql/opt_range.cc2149)

SQL_SELECT::test_quick_select()函數用于實際的處理估計範圍查詢需要的記錄數和時間。從函數名和注釋來看,該函數是用于檢查範圍查詢中key是否可用,而從函數邏輯來看,該函數主要用于對範圍查詢進行處理。

處理邏輯有以下幾步:

首先,根據記錄數,計算處掃描時間(scan_time)和讀取(read_time)。計算公式如下:

 

scan_time=records/5 +1  //其中5表示每個where條件進行比較的次數,該值爲常量。

read_time=((file_len)/4096+2)+scan_time+1.1   //其中4096表示IO buffer size

 

如果read_time的值小于2.0並不強制使用索引,那麽就不使用索引進行查詢。否則,進行索引查詢。

         接著,根據查詢條件,調用get_mm_tree()函數生成所有查詢條件的一棵查詢樹。接下來的一系列操作將對查詢樹進行優化。具體get_mm_tree()函數的分析參照以下內容。

接下來,計算最小覆蓋索引進行全索引讀的代價。該邏輯需要首先查找合適的索引,以便于進行全表掃描。由于輔助索引(secondary key)是主鍵索引(primary key)的子集,並且無法比較兩者的鍵長對IO的影響,因此,mysql選擇了首先利用輔助索引,只有當輔助索引不能覆蓋查找的條件或者輔助索引包含表中的列,才選擇主鍵進行查詢。根據索引,計算索引讀取(key_read_time)時間,計算公式如下。如果得到的read_time大于key_read_time,則read_time=key_read_time

 

key_read_time=(records+keys_per_block-1)/keys_per_block 

keys_per_block=(block_size/2/(key_len+ref_len+1)) 

//block_size是文件的block大小,mysql默認爲16K

//key_len是索引的鍵長度;

//ref_len是主鍵索引的長度;

 

然後,調用get_best_group_min_max()函數,用于獲得最優的處理group bymax/min的查詢計劃。具體內容參照該函數的具體介紹。

如果不需要索引合並,調用get_key_scans_params()函數,獲得最優的範圍查詢計劃,具體處理邏輯參照以下函數詳解。調用get_best_ror_intersect ()函數,獲得最優的非覆蓋的ROR交叉執行計劃,調用get_best_covering_ror_intersect()函數根據get_best_ror_intersect()函數提供的數據建立覆蓋的ROR交叉執行計劃。

否則,調用get_best_disjunct_quick()函數,獲得索引合並的最優執行計劃。具體內容參照以下具體介紹。

最後,調用TRP_RANGE::make_quick()函數,根據最優的範圍查詢計劃,執行快速查詢。詳細見以下函數的詳細介紹。

該函數簡化後的流程圖如下圖所示:

 

MySQL查詢優化器源碼分析

 

20) get_mm_tree()(sql/opt_range.cc5518)

get_mm_tree()函數用于根據所有查詢條件的鍵,生成一顆查詢樹。如果查詢條件的類型是COND_ITEM類型,即查詢條件也是一個查詢條件,則遞歸調用get_mm_tree()函數生成子查詢樹。如果爲簡單的查詢類型,則構建查詢樹。如果查詢條件類型是betweenin以及默認調用get_full_func_mm_tree()函數(sql/opt_range.cc5474),對查詢條件進行轉換後,構建查詢樹。例如:(c BETWEEN a AND b)轉換爲(c>=a AND c<=b)(c NOT BETWEEN a AND b)轉化爲(c<=a or c>=b)(f in (a,b,c))轉換爲(f=a OR f=b OR f=c)

get_full_func_mm_tree()函數的主要處理邏輯在get_func_mm_tree()函數(sql/opt_range.cc5180)中實現,後者對不同的情況進行了處理。

21) get_best_group_min_max()(sql/opt_range.cc9407)

get_best_group_min_max()函數用于獲得最優的處理group bymax/min的查詢計劃。該處理過程分別對不同的組合情況進行了處理,具體的處理過程較複雜,設計到很多數學推理和邏輯組合的知識。

22) get_key_scans_params()(sql/opt_range.cc4923)

get_key_scans_params()用于獲得最優的範圍查詢計劃。如果使用索引查找,那麽調用check_quick_select()函數獲得估計查詢的記錄數,在僅使用一個索引查找的情況下,讀取時間(found_read_time)的值如表中(1)公式所示。否則,讀取時間的值如表中(2)的公式所示。如果此時read_time大于found_read_time的值,則read_time=found_read_time,生成read_plan並且返回。

 

(1)只使用一個索引讀取

found_read_time=key_read_time+cpu_cost+0.01 

//0.01是爲了避免範圍掃描和索引掃描排序

cpu_cost=found_records/5 

//5表示每個where條件進行比較的次數

//found_records表示check_quick_select()獲得的查詢記錄數。

(2)多個範圍索引讀取

found_read_time=found_records+range_count+cpu_cost+0.01

 

該函數的核心是調用check_quick_select()函數(sql/opt_range.cc7519)獲取查找的記錄數,而check_quick_select()函數調用check_quick_keys()函數(sql/opt_range.cc7628)通過聚集主鍵索引獲得記錄數。而check_quick_keys()函數是一個遞歸過程,通過掃描主鍵索引的SEL_ARG樹,估計查詢的記錄數。SEL_ARG結構在定義之前的說明中,對該結構進行了詳細解釋,在此不做介紹。

23) get_best_ror_intersect()(sql/opt_range.cc)

get_best_ror_intersect()函數獲得最優的非覆蓋的ROR交叉執行計劃(ROR-intersection plan)。該過程在函數注視中命名爲“非覆蓋ROR-intersection查詢算法(non-covering ROR-intersection search algorithm)”,從算法描述中可以看出,主要用于獲得or查詢的最小查詢記錄數和讀取時間。

24) get_best_disjunct_quick()(sql/opt_range.cc)

get_best_disjunct_quick()函數用于獲得索引合並的最優執行計劃。該過程中使用SEL_IMERGE結構,該結構用于索引的合並操作。索引合並的代價計算在函數的注釋中給出,如表中所示。其中index_reads是所有通過索引讀的代價之和;rowid_to_row_scan如果是聚集主鍵索引,那麽讀的代價就是主鍵索引讀的代價,否則根據文件的偏移量和block大小計算,此外還考慮到block中包含記錄數和空block的情況;unique_use計算唯一索引讀的代價。

 

index_merge_cost=index_reads+rowid_to_row_scan+unique_use

 

25) TRP_RANGE::make_quick()(sql/opt_range.cc1881)

TRP_RANGE::make_quick()函數根據最優的範圍查詢計劃,執行範圍快速查詢確定執行計劃。其中調用get_quick_select()函數(sql/opt_range.cc7903)通過鍵值和SEL_ARG樹創建QUICK_RANGE_SELECT結構,並調用get_quick_keys()函數(sql/opt_range.cc7945)獲得所有可能的子範圍。其中get_quick_keys()是一個遞歸過程。

26) choose_plan()(sql/sql_select.cc4913)

         choose_plan()函數用于獲得一個最優的join順序的執行計劃。如果使用STRAIGHT_JOIN,調用optimize_straight_join()函數進行優化。否則,調用greedy_search()函數搜索一個最優的執行計劃(之前的實現處理函數是find_best(),以後將要廢棄)。optimize_straight_join()greedy_search()函數參照以下詳細分析。

該函數簡化後的流程圖如下圖所示:

 

MySQL查詢優化器源碼分析

 

27) optimize_straight_join()(sql/sql_select.cc5108)

在分析optimize_straight_join()函數邏輯之前,首先對STRAIGHT_JOIN這種join方式進行簡單介紹。STRAIGHT_JOIN MySQL 對標准 SQL 的擴展,用于在多表查詢時指定表載入的順序。在 JOIN 表連接中,同樣可以指定表載入的順序[1]。理解了這一點,那麽以下邏輯就容易理解了。

         optimize_straight_join()函數對每一個join表,基于現有的部分執行計劃,查找最優的訪問計劃,並將該計劃添加到執行計劃中。該過程主要調用best_access_path()函數,具體處理邏輯參照以下具體分析內容。

28) best_access_path()(sql/sql_select()4365)

best_access_path()基于現有“部分查詢計劃(partial QEP)”查找最優的訪問計劃,並添加到執行計劃中。該過程根據當前可用的索引區的數目,對每一部分索引查找最優的計劃,並計算訪問計劃的記錄數和讀取時間。其中針對不同的索引類型,對記錄數和讀取時間的估計方式也不同。

29) greedy_search()(sql/sql_select.cc5219)

greedy_search()函數使用混合的貪婪/有限窮舉搜索算法,查找最優的查詢計劃。每次評估還未優化的表的期望值(promising),選擇期望最大的表來擴展當前“部分查詢計劃(partial QEP)”。期望值(promising)最大的表是帶來的擴展代價最小的沒有優化的表。該過程調用best_extension_by_limited_search()函數,用于實際有限次的窮舉搜索最優的查詢計劃。具體best_extension_by_limited_search()函數的內容見以下分析。

 

30) best_extension_by_limited_search()(sql/sql_select.cc5425)

         best_extension_by_limited_search()函數用于有限次的窮舉搜索最優查詢計劃。該過程利用遞歸的深度優先搜索的方式進行搜索,搜索的深度通過變量“search_depth”控制。從該函數之前的注釋中,給出了該函數的算法思想。

從函數邏輯來看,該函數依次每個未被優化的join表,調用best_access_path()函數,查找最優的訪問計劃,估計當前查詢的記錄數和讀取時間,與現有的“部分查詢計劃”的查詢記錄數和讀取時間進行比較,如果優于現有的查詢計劃,則保存當前最優的訪問計劃到“部分查詢計劃”。

如果目前的搜索的深度大于1,遞歸調用best_extension_by_limited_search()函數,並且search_depth1。否則,當前保存的是“部分最優的查詢計劃(best partial QEP)”或者“完全最優的查詢計劃(best complete QEP)”。

該函數簡化後的流程圖如下圖所示:

 

MySQL查詢優化器源碼分析

 

31) get_best_combination()(sql/sql_select.cc5793)

get_best_combination()函數根據greedy_search()函數得到的“最優查詢計劃”,獲得最優的join結構,爲執行查詢做准備。

32) make_join_select()(sql/sql_select.cc6374)

make_join_select()函數用于執行各種不同情況的join查詢。該函數通過join時,連接表的不同搜索方式(唯一索引查找、ref查找、快速範圍查找、合並索引查找、全表掃描等不同方式),進行join操作的處理。

33) JOIN::exec()(sql/sql_select.cc1817)

JOIN::exec()函數根據執行計劃,針對不同的查詢(存儲過程、表定義查詢、where查詢、having查詢、order by條件、join查詢(單純的joinjoingroupjoingroup by以及order by等不同查詢)等查詢),進行相應的查詢處理。join查詢中並調用do_select()函數,對所有的join表執行join查詢操作,具體函數處理如下所示。

34) do_select()(sql/sql_select.cc11431)

do_select()函數對所有的join表進行join查詢操作。並將join查詢後的結果通過socket發送。

35) st_select_lex::cleanup()(sql/)

st_select_lex::cleanup()函數用于清理查詢的臨時結構、臨時變量。該過程調用JOIN::destroy()函數清理join操作使用的存儲結構和變量。

 

總結

通過對mysql查詢優化器的分析,對查詢的邏輯處理流程有一定的深入了解。通過對簡單的語句進行調試並得出以上分析文檔,以上文檔更側重函數的邏輯處理過程。由于時間原因,對各種不同類型的查詢,未進行逐一的跟蹤調試,對工作原理和優化策略不敢妄自分析。因此,對不同類型的查詢,mysql查詢優化器的工作原理和優化策略,還需要進一步的深入研究。

由于跟蹤調試語句的局限性和個人目前能力有限,對源碼處理邏輯的理解不可避免存在錯誤,但本人已盡力做到准確。希望有相關研究經驗的同事,給予批評和指正,共同討論、共同進步。

 

進一步的研究

         1、對不同的查詢語句進行跟蹤調試,梳理優化處理策略。

         2、全面分析查詢優化器的工作原理和優化策略。

 

參考資料

[1]、《MySQL STRAIGHT_JOIN NATURAL JOIN http://www.5idev.com/p-php_mysql_straight_join_natural_join.shtml

更多相關文章
  •          基于之前對MySQL查詢優化器的源碼進行分析,對MySQL查詢優化器的處理邏輯和工作原理有較深入的了解.然而,僅僅通過源碼表象並不能清晰的了解MySQL查詢優化器針對不同的SQL查詢,所進行的邏輯處理.因此,爲了進一步了解不同的SQL查詢,查詢優化器的優化過程,進行了一系列的SQL ...
  • 緊接著之前的<MySQL 查詢優化器實驗分析(四)>中的內容,以下對測試過程進行詳細分析.2.5 LEFT JOIN查詢       該測試主要用于測試LEFT JOIN與JOIN的處理邏輯上的差異,具體查詢處理邏輯如下所示: JOIN:prepare階段setup_tables():同 ...
  • 緊接著之前的<MySQL 查詢優化器實驗分析(五)>中的內容,以下對測試過程進行詳細分析.
  • 緊接著之前的<MySQL 查詢優化器實驗分析(三)>中的內容,以下對測試過程進行詳細分析.將在接下來的<MySQL 查詢優化器實驗分析(五)>文檔中給出.
  • 緊接著之前的<MySQL 查詢優化器實驗分析(二)>中的內容,以下對測試過程進行詳細分析.
  •        一.MySQL 查詢優化器是如何工作的        MySQL 查詢優化器有幾個目標,但是其中最主要的目標是盡可能地使用索引,並且使用最嚴格的索引來消除盡可能多的數據行.最終目標是提交 SELECT 語句查找數據行,而不是排除數據行.優化器試圖排除數據行的原因在于它排除數據行的速度越 ...
  • 查詢優化器內核剖析第一篇查詢優化器內核剖析第二篇:産生候選執行計劃&執行計劃成本估算查詢優化器內核剖析第三篇:查詢的執行與計劃的緩存 & Hint提示  查詢優化器內核剖析第四篇:從一個實例看執行計劃   查詢優化器內核剖析第五篇:進一步的了解執行計劃 查詢優化器內核剖析第七篇:執行 ...
  • 查詢優化器內核剖析第一篇查詢優化器內核剖析第二篇:産生候選執行計劃&執行計劃成本估算查詢優化器內核剖析第三篇:查詢的執行與計劃的緩存 & Hint提示 查詢優化器內核剖析第四篇:從一個實例看執行計劃   
一周排行