MySQL 優化器引數derived_merge導致多表關聯SQL效能及其低下

清風艾艾發表於2019-05-31

    最近,MySQL維護中,遇到一個問題,通條SQL語句,在mysql 5.6的測試環境中執行速度不到1秒,但是在

mysql 5.7生產環境中執行卻要近5分鐘,mysql 5.7中同樣的資料庫同樣的資料量,更新完表的統計資訊後執行

速度還是要2分鐘。本次問題的處理與sql語句本身沒有關係,只跟mysql資料庫自身的優化器引數相關,下面是

問題的分析排查過程,問題分析中的sql語句不需要顯示,可以明確sql是多表join連線並且業務不允許更改。

    1、首先,檢視測試環境和生產環境中,mysql的sql語句的執行計劃

--測試環境,執行計劃只需顯示區域性能說明問題即可

--生產環境,執行計劃只需顯示區域性能說明問題即可

    2、從測試與生產環境sql語句的對比可以明顯發現,sql的執行計劃不一致,後續排查中發現

a、測試環境中sql涉及的表和索引的統計資訊都是當天最新的,而生產環境中的相關表和索引的統計資訊比較陳舊

b、測試環境 mysql大版本為5.6,生產環境mysql大版本為5.7

    3、問題處理

a、由於sql執行計劃不一致,且生產環境統計資訊比較舊,重新收集生產環境表的統計資訊,收集後sql的執行速度沒有

提高,相比測試依然很慢。

b、關注測試環境執行計劃derived和<auto_key>,該特性與mysql 的引數derived_merge相關,檢視該引數的設定情況

--測試環境

MySQL [(none)]> show global variables like '%switch%';

+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| Variable_name    | Value                                                                                                                                                                                                                                                                                                                                            |

+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| optimizer_switch | index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,....... |

+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

MySQL [(none)]> 

--生產環境,為了方便說明問題,省略了多餘的引數顯示

mysql> show  variables like '%switch%';

+------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| Variable_name    | Value                                                                                                                                                                                                                                                                                                                                                                                                             |

+------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| optimizer_switch | ......, derived_merge=on |

+------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql>

c、根據官方說明引數derived_merge是在mysql5.7版本中引入的,作用就是對join (select)表連線合並,本次問題sql有

大量的join (select),導致sql執行結果集合並,sql執行速度及其緩慢。

d、通過session級別臨時取消該引數,觀察sql執行計劃,發現sql執行計劃正常,且sql執行速度不到1秒與測試環境相近

--取消優化器derived_merge引數

mysql> set optimizer_switch="derived_merge=off";

ERROR 2006 (HY000): MySQL server has gone away

No connection. Trying to reconnect...

Connection id:    8980

Current database: mysql

Query OK, 0 rows affected (0.02 sec)

mysql> 

--觀察問題sql執行計劃,此時生產環境執行計劃與測試環境相同


--問題sql執行速度由原先的近5分鐘到現在的1秒左右



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29357786/viewspace-2646294/,如需轉載,請註明出處,否則將追究法律責任。

相關文章