国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

統計--VARCHAR與NVARCHAR在統計預估上的區別

2024-07-21 02:48:33
字體:
來源:轉載
供稿:網友
統計--VARCHAR與NVARCHAR在統計預估上的區別

最近遇到一個問題,當查詢使用到模糊查詢時,由于預估返回行數過高,執行計劃認為索引查找+Key Lookup的成本過高,因此采用Clustered Index Scan的方式,消耗大量邏輯IO,執行計劃較差。

經過測試,發現對于模糊查詢,NVARCHAR和VARCHAR的預估返回行數差距很大,因此拿出來供大家一起測試。

首先生成測試數據,分別創建TB101和TB102的表,表上有相同的聚集索引和非聚集索引,表中有100w數據,創建測試數據腳本如下:

DROP TABLE TB101GODROP TABLE TB102GOSELECT CAST(NCHAR(19968+20902*RAND(RID))+NCHAR(19968+20902/2*RAND(RID))+NCHAR(19968+20902/3*RAND(RID)) AS varchar(40)) AS RName,*INTO TB101FROM(SELECT ROW_NUMBER()OVER(ORDER BY T1.OBJECT_ID DESC) AS RID,T1.* FROM sys.all_objects T2CROSS JOIN sys.all_columns T1) AS TWHERE T.RID<1000000GOSELECT * INTO TB102 FROM TB101GOALTER TABLE TB102ALTER COLUMN RName NVARCHAR(40)GOCREATE UNIQUE CLUSTERED INDEX IDX_RID ON TB101(RID)GOCREATE UNIQUE CLUSTERED INDEX IDX_RID ON TB102(RID)GOCREATE INDEX IDX_Name ON TB101(RName)GOCREATE INDEX IDX_Name ON TB102(RName)GOEXEC sp_spaceused 'TB101'EXEC sp_spaceused 'TB102'GO

兩表使用空間相同,數據相同。

測試前先更新下統計:

--更新統計UPDATE STATISTICS TB101 WITH FULLSCANGOUPDATE STATISTICS TB102 WITH FULLSCAN

開始測試1

SELECT RName FROM TB101WHERE RName LIKE '你好%'

其執行計劃為:

測試2:

SELECT RName FROM TB102WHERE RName LIKE N'你好%'

感謝網友“害怕飛的鳥”的提醒,我們測試了以中文開頭的模糊查詢,需要測試以字母開頭的模糊查詢。

因此重新創建測試用例(生成新的測試數據目的為了避免查詢值落在統計的兩端,原理請參考大神高繼偉的SQL Server 統計信息(Statistics)-概念,原理,應用,維護)

準備測試數據:

SELECT CAST(NCHAR(65+25*RAND(RID))+NCHAR(24*RAND(RID))+NCHAR(19968+20902/2*RAND(RID))+NCHAR(19968+20902/3*RAND(RID)) AS varchar(40)) AS RName,*INTO TB103FROM(SELECT ROW_NUMBER()OVER(ORDER BY T1.OBJECT_ID DESC) AS RID,T1.* FROM sys.all_objects T2CROSS JOIN sys.all_columns T1) AS TWHERE T.RID<1000000GOSELECT * INTO TB104 FROM TB103GOALTER TABLE TB104ALTER COLUMN RName NVARCHAR(40)GOCREATE UNIQUE CLUSTERED INDEX IDX_RID ON TB103(RID)GOCREATE UNIQUE CLUSTERED INDEX IDX_RID ON TB104(RID)GOCREATE INDEX IDX_Name ON TB103(RName)GOCREATE INDEX IDX_Name ON TB104(RName)GO

測試1:

SELECT RName FROM TB103WHERE RName LIKE 'A你好%'

測試2:

SELECT RName FROM TB104WHERE RName LIKE N'A你好%'

通過上面四個測試,可以得出以下結論:

1. 當字段的數據類型為NVARCHAR時,無論模糊查詢以中文還是英文字母開頭,預估返回行數和實際返回行數相差不多

2. 當字段的數據類型為VARCHAR且模糊查詢以英文字母開頭,預估返回行數和實際返回行數相差不多

3. 當字段的數據類型為VARCHAR且模糊查詢以中文開頭,預估返回行數和實際返回行數相差較大。

--==============================================================

當預估返回行數與實際返回行數相差較大時,就很容易生成較差的執行計劃,如對于查詢:

SELECT * FROM TB101WHERE RName LIKE '你好%'

由于預估索引查找會返回50w的數據,查詢優化器引擎認為如果使用索引查找+Key Lookup就會消耗上200W+的邏輯IO, 效率會遠低于表掃描,因此有了下面的執行計劃:

而實際上,經過索引查找后,只會返回少量的數據行,這些行做Key Lookup也只會消耗少量的邏輯IO,因此索引查找+Key Lookup是最高效的。

解決辦法:

對于這種問題,可以有幾種辦法處理:

1. 強制索引查找

SELECT * FROM TB101 WITH(FORCESEEK)WHERE RName LIKE '你好%'

2. 使用隱式轉化

SELECT * FROM TB101WHERE RName LIKE N'你好%'

經過一次隱式轉換后,預估返回行數出奇地下降下來,生成了正確的執行計劃(看來隱式轉換也是有存在價值地哦)

3. 如果不想修改程序的話,可以考慮使用參數化和執行計劃指南來實現

--=========================================================================================

總結(以下結論未經過大神認證,請自行組鑒別正確性):

1. 當字段的數據類型為NVARCHAR時,無論模糊查詢以中文還是英文字母開頭,預估返回行數和實際返回行數相差不多

2. 當字段的數據類型為VARCHAR且模糊查詢以英文字母開頭,預估返回行數和實際返回行數相差不多

3.當字段的數據類型為VARCHAR且模糊查詢以中文開頭,預估返回行數和實際返回行數相差較大。

4. 隱式轉換未必會導致表掃描或索引掃描,也未必會導致執行計劃質量不優。

--===========================================================


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 四平市| 科技| 灵璧县| 江达县| 杨浦区| 荥经县| 息烽县| 遂川县| 德阳市| 大同县| 桑植县| 巩留县| 巴林左旗| 南涧| 桐乡市| 彰化市| 通道| 墨竹工卡县| 丹巴县| 金湖县| 大名县| 平邑县| 淳安县| 陈巴尔虎旗| 广宁县| 澄城县| 利津县| 迭部县| 肥东县| 闸北区| 交口县| 泗水县| 梁平县| 扶绥县| 来宾市| 长丰县| 八宿县| 隆林| 长治县| 苏尼特左旗| 南宁市|