我們知道sql在底層的執行給我們上層人員開了一個窗口,那就是執行計划,有了執行計划之后,我們就清楚了那些爛sql是怎么執行的,這樣
就可以方便的找到sql的缺陷和優化點。
一:執行計划生成過程
說到執行計划,首先要知道的是執行計划大概生成的過程,這樣就可以做到就心中有數了,下面我畫下簡圖:
1. 分析過程
這三個比較容易理解,首先我們要保證sql的語法不能錯誤,select和join的表是必須存在的,以及你是有執行這個sql的權限,對不對。。。
這樣我們就走完了執行計划生命周期的第一個流程。
2. 編譯過程
保證了上面sql這三點的話,引擎就必須硬着頭皮看你這么一大坨爛sql,該刪的刪,該改的改,該轉換的轉換,比如說你的“子查詢”會轉化為
“表連接”等等。。。其實也挺難為引擎的,舉個例子吧。
<1>子查詢生成的sql:
<2>join生成的sql:
從上面的兩個結果中,你可以看到,大家都是玩join的,如果你仔細看的話,會發現一個是“哈希匹配”,一個是“嵌套循環”,為什么不一樣,這
當然是引擎根據很多情況綜合評選出來的,比如說:磁盤IO,邏輯讀,資源占用,硬件環境等等。。。這也是所謂的“計划選優”操作。
3.執行過程
既然執行計划都選出來了,理所當然就要執行了,執行完后會把sql和執行計划放入緩存,這樣下次有同樣的sql過來的時候就可以直接從
Cache中提取了,不需要再次生成計划了,你也看到,生成執行計划還是比較消耗CPU時間的。
二:看看sql和執行的計划的緩存
剛才也說了,sql和plan都已經放入緩存了,那我的好奇心比較強,我就想看看sql和plan到底在哪,並且長的是個什么丑樣子,剛好
sqlserver還是比較能夠滿足我們G點的。
1. 為了方便查看緩存,我需要先將所有的緩存清空,比如下面的語句。
DBCC freeproccache SELECT c.* FROM dbo.Category AS c JOIN dbo.Product AS p ON c.CategoryId=p.CategoryId WHERE c.CategoryId=23794
2. 通過sys.dm_exec_cached_plans拿到sql和plan的指針(plan_handle),如下圖
SELECT * FROM sys.dm_exec_cached_plans
從圖中你看到了兩個adhoc(即時查詢),分別是我在第一步執行的join查詢和我在第二步執行的這個select。
3. 現在我們已經拿到了2個adhoc的plan_handle,然后通過dm_exec_sql_text查看他們的sql分別是怎樣?
4. 看完text緩存,接下來我們繼續看看sql的plan緩存在哪?可以通過dm_exec_query_plan來查看。
上面的query_plan字段就是所謂的執行計划,以xml的形式保存在字段中。。。所以說解析這個xml還是很費時間的
5.查看sql的執行計划
select * from (
SELECT *,(select text from sys.dm_exec_sql_text(plan_handle)) sqlText FROM sys.dm_exec_cached_plans
) a where sqlText = 'select * from [dbo].[Card] where Id=3'
6.刪除執行計划
DBCC FREEPROCCACHE(0x060016009A5D562DD01D79DA0100000001000000000000000000000000000000000000000000000000000000)
參考來源:路徑丟了