通過如下測試驗證,首先建立數據分布不平均的測試表。
USE?tempdb GOCREATE?TABLE?_t( ????c?varchar(50) );CREATE?INDEX?IX_c?ON?_t(?c?);GO--?加入?10000?條數據INSERT?_tSELECT?(9999?+?id)?FROM(????SELECT?TOP?10000?id?=?ROW_NUMBER()?OVER(?ORDER?BY?GETDATE()?)????FROM?sys.all_columns?a,?sys.all_columns )ID --?將?100?-?10000?的數據變成相同值UPDATE?_t?SET?c?=?''?WHERE?c?>=?'10100'
然后通過 varhcar和nvarchar值分別測試滿足條件1條和滿足條件8900條的執行計劃預估行數。
ALTER?INDEX?IX_c?ON?_t?REBUILD;GOSET?SHOWPLAN_ALL?ONGOSELECT?*?FROM?_t?WHERE?c?=?'10005';?????--?實際1條GOSET?SHOWPLAN_ALL?OFF;GOALTER?INDEX?IX_c?ON?_t?REBUILD;GOSET?SHOWPLAN_ALL?ONGOSELECT?*?FROM?_t?WHERE?c?=?N'10005';?????--?實際1條GOSET?SHOWPLAN_ALL?OFF;GOALTER?INDEX?IX_c?ON?_t?REBUILD;GOSET?SHOWPLAN_ALL?ONGOSELECT?*?FROM?_t?WHERE?c?=?'';??????????--?實際9900條GOSET?SHOWPLAN_ALL?OFF;GOALTER?INDEX?IX_c?ON?_t?REBUILD;GOSET?SHOWPLAN_ALL?ONGOSELECT?*?FROM?_t?WHERE?c?=?N'';?????????--?實際9900條GOSET?SHOWPLAN_ALL?OFF;GO
得到的查詢計劃預估行數如下圖所示
從圖中顯示的預估數據行數可以看到,對于varchar值(不需要隱匿的數據類型轉換),其預估的結果是準確的。但對于nvarchar值,不管指定的值是只有一條數據,還是有8900條數據匹配,其預估的結果都是99.0099,這說明預估并沒有考慮我們指定的值。
進一步用變量測試
ALTER?INDEX?IX_c?ON?_t?REBUILD;GOSET?SHOWPLAN_ALL?ONGODECLARE?@v?varchar;SELECT?*?FROM?_t?WHERE?c?=?@v;?--?varcharGOSET?SHOWPLAN_ALL?OFF;GOALTER?INDEX?IX_c?ON?_t?REBUILD;GOSET?SHOWPLAN_ALL?ONGODECLARE?@nv?nvarchar;SELECT?*?FROM?_t?WHERE?c?=?@nv;?--?nvarcharGOSET?SHOWPLAN_ALL?OFF;GO
結果如下圖所示:
不管是varchar,還是nvarchar的變量,預估的行數都是99.0099,這個值與使用nvarchar常量值的結果一樣,看來sql Server查詢優化器應該確實把 GetRangeThroughConvert 的結果看成變量了,這個應該是設計上考慮不太周全的地方了,畢竟指定固定常量值的時候,GetRangeThroughConvert的結果應該也是確定值才對。
本文講解了SQL Server的相關內容,更多相關內容請關注php中文網。
相關推薦:
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END