天天看點

RDS SQL Server - 專題分享 - 巧用執行計劃緩存之Single-used plans背景引入什麼是Single-used Plans如何發現Single-used Plans執行計劃緩存中有多少Single-used PlansSingle-used Plans對性能的影響解決Single-used Plans問題最後總結

執行計劃緩存是sql server記憶體管理中非常重要的特性,這篇系列文章我們探讨執行計劃緩存設計中遇到的single-used plans問題,以及如何發現、如何定性和定量分析single-used plans帶來的影響,最後我們使用兩種方法來解決這個問題。

要解釋清楚什麼是single-used plans,首先需要解釋sql語句執行計劃緩存是什麼?sql server執行每一條sql語句之前,會從執行計劃緩存記憶體中檢視是否存在本條語句的執行計劃,如果不存在,會将其編譯、選擇最優路徑、生成執行計劃,然後會将執行計劃存儲在一塊專門的記憶體區域中(這塊記憶體叫着執行計劃緩存),以供下次該語句執行直接從執行計劃緩存中擷取編譯完畢的執行計劃。以此來節約資料庫系統對于查詢語句編譯、生成執行計劃過程的性能開銷,提高sql語句的執行效率。

而single-used plans是指那些第一次執行後被緩存起來的執行計劃,而後再也沒有被重複利用過的執行計劃緩存。其中ad hoc query(即席查詢)就是典型的single-used plans中的一種。

從上一節我們可以大緻知道,single-used plans僅會第一次被使用(從名字也可以很好了解到這一點),是以,實際上single-used plans是對sql server記憶體空間和cpu資源的浪費,對資料庫性能有一定的損害。那麼,我們如何來發現single-used plans呢?我們可以使用下面的查詢語句:

我的測試執行個體展示的查詢結果如下:

RDS SQL Server - 專題分享 - 巧用執行計劃緩存之Single-used plans背景引入什麼是Single-used Plans如何發現Single-used Plans執行計劃緩存中有多少Single-used PlansSingle-used Plans對性能的影響解決Single-used Plans問題最後總結

當我們可以有效的發現single-used plans以後,我們可能又會問:到底我的sql server資料庫執行個體中,有多少執行計劃緩存是屬于single-used plans類型呢?可以從兩個次元來分析:

single-used plans記錄總數

single-used plans總的執行計劃占用的記憶體空間大小

可以使用以下的查詢語句來回答這個問題。

我的測試執行個體執行結果如下截圖:

RDS SQL Server - 專題分享 - 巧用執行計劃緩存之Single-used plans背景引入什麼是Single-used Plans如何發現Single-used Plans執行計劃緩存中有多少Single-used PlansSingle-used Plans對性能的影響解決Single-used Plans問題最後總結

從這個結果我們可以得出如下single-used plans的資料:總的single-used plans記錄數為73,記憶體空間占用大小為13912 kb。

就單單一條single-used plan來看的話,對資料庫系統的性能影響很小,小到可以忽略的地步,是以,資料庫執行計劃緩存中,存在少量的single-used plans是很正常的,可以不用太關注。但是,如果single-used plans大量存在的話,可能就會對系統帶來比較嚴重的性能影響。

定性分析大量single-used plans對資料性能的影響,主要展現在以下幾個方面:

總的執行計劃緩存使用率不高:因為存在大量不能被重複利用的執行計劃緩存,進而拉低了執行計劃緩存整體使用率

浪費執行計劃緩存中記憶體的開銷:每一條執行計劃緩存或多或少會占用一定的執行計劃緩存記憶體空間,大量的single-used plans導緻了記憶體空間的浪費

導緻cpu使用率的上升:每一條sql語句執行計劃的編譯、最優路徑選擇和執行計劃緩存,這些過程都需要消耗系統cpu資源,如果大量存在single-used plans,會導緻系統cpu使用率的上升。

舉一個最為極端的例子,假設執行計劃緩存中存儲的所有執行計劃都是single-used plans的話,那麼導緻的嚴重後果是:

執行計劃緩存使用率就是0%,因為沒有任何的執行計劃被重用

執行計劃緩存這種設計就毫無意義,因為緩存起來也沒有被重用

浪費執行計劃緩存的記憶體開銷和cpu開銷

以上是定性分析single-used plans對系統性能的影響,那麼到底single-used plans達到哪個數量級,占比多少的時候,我們需要密切關注呢?雖然微軟沒有官方的推薦數字,但是個人比較推薦的兩個數字是2gb和50%,即:所有的single-used plans使用的記憶體空間超過2gb或者記憶體空間使用占比超過50%。當然最終也可能取決于sql server可以使用的最大記憶體數量。

執行結果如下所示:

RDS SQL Server - 專題分享 - 巧用執行計劃緩存之Single-used plans背景引入什麼是Single-used Plans如何發現Single-used Plans執行計劃緩存中有多少Single-used PlansSingle-used Plans對性能的影響解決Single-used Plans問題最後總結

從這個執行結果來看,在我的sql server測試執行個體上,single-used plans占用的執行計劃記錄數為72條,記憶體空間占用14016 kb;single-used plans執行計劃記錄數占總的百分比為39.78%,記憶體空間占用比例為50.59%。

從定量分析小結,發現我的測試執行個體,single-used plans占用執行計劃緩存記憶體比例已經超過50%了,是解決single-used plans問題的時候到了。

第一種方法是手動清理single-used plans,當然,你也可以很暴力的将所有執行計劃緩存清空,進而也就清理了single-used plans,但是這樣會誤殺很多有用的無辜的執行計劃緩存,進而導緻這些執行計劃重編譯,影響性能。我們推薦使用下面的方法,僅清空哪些single-used plans,方法如下:

除了手動清理single-used plans執行計劃緩存外,另外一個更強大的功能是修改sql server 執行個體級别的配置選項optimize for ad hoc workloads。為了解決single-used plans帶來的問題,微軟從sql server 2008開始引入了這個全新選項,當打開這個選項以後,一個ad hoc的查詢語句在第一次執行的時候,系統會建立一個“compiled plan stub”,并不會将執行計劃緩存起來,隻有當第二次該語句再被執行的時候,執行計劃才會被緩存在記憶體中,進而避免了single-used plans帶來的問題。配置這個選項的方法很簡單,參見以下語句:

這篇文章讨論了執行計劃緩存中的single-used plans帶來的問題,如何發現,如何去定量和定性分析,以及最後怎麼解決single-used plans的問題。