為什麼你的MySQL效能差?函式、儲存過程和觸發器都確認無誤嗎?
MySQL儲存過程、函式和觸發器是開發人員常打交道的三大名詞,但是,這三個過程可能會對資料庫效能造成嚴重影響,尤其是函式中出現“死”程式碼時,其他兩個過程都會受到牽連,以下是作者進行的一些基本測試,通過對比更好得衡量三者對資料庫效能的影響。
觸發器和儲存過程對效能影響的重要原因:函式“死”程式碼
儘管所有開發人員都知道“死”程式碼(永遠不會被執行的程式碼)不應該出現在程式碼行中,但可能並不清楚一行“死”程式碼到底可以對效能造成多大影響。“死”程式碼可以顯著減緩函式執行、儲存過程和觸發器的響應時間,我們必須認真清理不需要的程式碼,以下是具體示例:
分析MySQL儲存過程函式
讓我們比較以下四個簡單的儲存函式(在MySQL 5.7中):
函式1:
該函式只是宣告一個r變數並返回它的值,這是一個虛擬函式。
函式2:
該函式呼叫另一個函式levenshtein_limit_n(計算levenshtein距離)。但是,由於IF 1=2條件永遠不會成立,因此這段程式碼永遠不會被執行,這與函式1的返回結果類似。
函式3:
函式3看起來很複雜,總共有四個條件,但因為這些條件永遠不會成立,因此同樣是“死”程式碼呼叫,結果與函式2和函式1相同。
函式4:
該函式與函式3情況相同,selectdoes_not_exit依舊不會被執行。
雖然所有函式最終返回的r值都為0,但這四段函式的效能有非常大的差異,為了衡量效能變化,我們使用benchmark功能對效能進行測試,在執行相同的1M次之後,四個函式的效能結果如下:
我們可以看到fun1只需要執行1.75 sec,具有一個死程式碼呼叫的fun 2需要執行2.45 sec,而func3(有四個永不執行的死程式碼呼叫)執行速度比func1()慢近3倍;,func3_nope()的響應時間與func3()完全相同。
視覺化函式的所有系統呼叫
要弄清楚函式呼叫過程發生了什麼,我們可以使用performance_schema / sys模式建立一個帶有 ps_trace_thread() procedure的跟蹤
1、獲取MySQL連線的thread_id:
2、在另一個連線中通過thread_id = 49執行ps_trace_thread
3、此時切換到原始連線(thread_id = 49)並執行:
sys.ps_trace_thread收集資料(10秒鐘,在此期間我執行了select func1()),然後它完成了集合並建立了點檔案:
我為上面的所有函式重複了這些步驟,然後建立了命令圖表。
結果如下:
Func1()
Func2()
Func3()
正如我們所看到的,每個“if”檢查都有一個sp / jump_if_not呼叫,後跟一個開啟表的語句。因此,解析“IF”條件就會對效能產生影響。
對於MySQL 8.0,我們還可以看到儲存過程的MySQL原始碼文件,這些文件記錄了它的實現方式,如下:
· 流量分析優化
· 生成程式碼後,優化低階sp_instr指令。優化主要集中在兩方面:
· 死程式碼刪除,
· 跳轉快捷方式。
· 這兩個優化是一起執行的,因為它們都涉及圖表中流量分析的問題,代表生成的程式碼。實現這些優化的程式碼是sp_head :: optimize()。
但是,這並不能解釋為什麼會執行“opening tables”,因此,我向官網提交了一個bug(MySQL Bug #91585 https://bugs.mysql.com/bug.php?id=91585)。
“死”程式碼如何影響觸發器效能?
當然,如果我們執行的函式不太多,我們可能注意不到這些效能上的差異,但是它會在觸發器內部產生影響。假設我們在表上有一個觸發器,每次更新該表時,它都會執行觸發器來更新欄位。比如,假設我們有一個名為“form”的表,我們只需要更新它的建立日期:
現在我們建立一個觸發器,它將呼叫我們的虛擬函式func1():
請記住:重複更新不會更改新的結果,因為我們沒有在觸發器中做任何事情。
如果再新增一個虛擬觸發器就會增加兩倍的開銷,即便觸發器沒有執行任何函式,同樣會引起減速:
現在,讓我們使用func3(它具有“死”程式碼,但功能相當於func1):
如果,我們從觸發器內的函式func3執行程式碼(而不是呼叫函式)將加快更新速度:
記憶體分配
即使程式碼永遠不會被執行,MySQL仍然需要分析每次執行解析儲存的過程或觸發器程式碼,並預先為其留出足夠的記憶體,這可能會導致記憶體洩漏,比如MySQL Bug #86821(https://bugs.mysql.com/bug.php?id=86821)所描述的。
結論
儲存過程和觸發器事件在執行時會被解析,即使是永不執行的“死”程式碼也會顯著影響批量操作的效能(例如,在觸發器內執行時)。這意味著通過設定“flag”來禁用觸發器(例如,if @trigger_disable =0 then ...)仍然會影響批量操作的效能。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31077337/viewspace-2158337/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【MySQL】MySQL(三)儲存過程和函式、觸發器、事務MySql儲存過程函式觸發器
- 七、函式-儲存過程-觸發器函式儲存過程觸發器
- 瞭解使用mysql 的檢視、儲存過程、觸發器、函式....MySql儲存過程觸發器函式
- MySQL 儲存過程和函式MySql儲存過程函式
- MySQL儲存過程和函式MySql儲存過程函式
- mysql和orcale的儲存過程和儲存函式MySql儲存過程儲存函式
- oracle儲存過程和觸發器Oracle儲存過程觸發器
- MySQL儲存過程 (即函式)MySql儲存過程函式
- mySql 儲存過程與函式MySql儲存過程函式
- MySQL入門--儲存過程(PROCEDURE)和儲存函式(FUNCTION)MySql儲存過程儲存函式Function
- 《MySQL 基礎篇》九:儲存過程、流程控制和觸發器MySql儲存過程觸發器
- mysql儲存過程procedure、函式function的用法MySql儲存過程函式Function
- MySQL自定義函式與儲存過程MySql函式儲存過程
- 儲存過程與儲存函式儲存過程儲存函式
- mysql儲存過程及日期函式實踐MySql儲存過程函式
- 函式儲存過程併發控制-案例函式儲存過程
- MySQL優化---儲存過程和儲存函式-1-轉自部落格園MySql優化儲存過程儲存函式
- 2020重新出發,MySql基礎,MySql檢視&索引&儲存過程&觸發器MySql索引儲存過程觸發器
- SQL server儲存過程函式SQLServer儲存過程函式
- SQL Server實戰五:儲存過程與觸發器SQLServer儲存過程觸發器
- day25-索引和函式及儲存過程索引函式儲存過程
- 如何匯出儲存過程、函式、包和觸發器的定義語句?如何匯出表和索引的建立語句?儲存過程函式觸發器索引
- MySQL儲存過程的建立和使用MySql儲存過程
- openGauss 函式及儲存過程支援函式儲存過程
- 儲存過程vs.函式QM儲存過程函式
- 深入mysql建立自定義函式與儲存過程的詳解MySql函式儲存過程
- mysql 儲存過程MySql儲存過程
- Mysql 儲存過程的使用MySql儲存過程
- 你知道js的函式過載是什麼嗎?JS函式
- Python操作MySQL儲存,這些你都會了嗎?PythonMySql
- [20190118]toad下如何除錯儲存過程和函式.txt除錯儲存過程函式
- MySQL之儲存過程MySql儲存過程
- MySQL---------儲存過程MySql儲存過程
- mysql儲存過程整理MySql儲存過程
- MySQL的物理儲存結構和session過程MySqlSession
- MySQL 高階 | 用儲存過程、定時器、觸發器來解決資料分析問題MySql儲存過程定時器觸發器
- mysql儲存過程的引數MySql儲存過程
- mysql 匯入匯出資料庫以及函式、儲存過程的介紹MySql資料庫函式儲存過程