萬級别的資料真的算不上什麼大資料,但是這個檔的資料确實考核了普通的查詢語句的性能,不同的書寫方法有着千差萬别的性能,都在這個級别中顯現出來了,它不僅考核着你sql語句的性能,也考核着程式員的思想。
公司系統的一個查詢界面最近非常慢,界面的響應時間在6-8秒鐘時間,甚至更長。檢查發現問題出現在資料庫端,查詢比較耗時。該界面涉及到多個表中的資料,基本表有150萬資料,關聯子表的最多的一個700多萬資料,其它表資料也在幾十萬到幾百萬之間。其實按這樣的資料級别查詢響應時間應該在毫秒級内,不應該有這麼長時間。那麼接下來就該進行問題排查了。
由于這個這界面的功能主要是資訊檢索,查詢比較複雜,太多的條件組合,使用存儲過程太多的局限性,是以查詢使用的是動态拼接的sql語句。查詢方式是最常用的1、擷取資料總數2、資料分頁。直接上代碼(部分條件)。

根據提示得知,整個查詢耗時花費在了分析和編譯為4秒,執行為0.7秒。查詢語句沒有發現什麼問題,那麼問題出現在了編譯,如果讓SQL語句執行原有的查詢計劃,那麼跳過編譯,隻需0.7秒就能得到結果。那麼如何做到預編譯,或者使用現有的執行計劃?
SQL Server有一優化算法,它儲存了以往執行sql語句的執行計劃,所有的執行計劃都會在sys.syscacheobjects表中存儲,如果目前sql語句在緩存表中能比對到,那麼它講執行比對到的執行計劃,而不再進行編譯。 那麼解決方法我們首先想到的是存儲過程(這就是我們面試或者理論中經常說的存儲過程有預編譯,平時也就是說說,不存在什麼深刻印象),是的它能實作預編譯,但是由于條件限制,查詢太過複雜,如果把沒有使用到查詢條件的表都關聯在一起反而影響到性能。排除存儲過程,我們另外想到的就是
EXEC SP_EXECUTESQL @Sql, N'@p NVARCHAR(50)',@p
為什麼SP_EXECUTESQL 能複用查詢計劃而普通sql語句不能,我們從緩存表中檢視就能發現問題
表中sql字段就是曆史執行計劃的查詢語句,如果sql比對成功那麼就會執行比對的執行計劃。普通sql語句很難與之比對,因為它不但包含了結構還包含了參數,複用率很低。而SP_EXECUTESQL 執行時隻存儲結構,參數不存儲,是以複用率很高。找到了解決方法,那麼直接行動。
總耗時0.5秒,無論參數如何改變基本都在0.5秒波動,基本符合了我們的要求,如果想進一步優化還可以進行表分區等其他優化方案。
當我們發現查詢速度慢時,有可能是分析和編譯占用了你的太多時間,是以簡化你的查詢語句、複用執行計劃能幫你走出困境。