我有一个生成错误执行计划的查询,我追溯到这样一个事实:执行Unicode转换会更改执行计划中的估计行数。
我有这张桌子
CREATE TABLE Orders
(
BusinessUnit VARCHAR(5) NOT NULL,
OrderNumber VARCHAR(10) NOT NULL,
CustomerId VARCHAR(20)
)
ALTER TABLE Orders ADD PRIMARY KEY(BusinessUnit, OrderNumber)
我在表格中插入了一堆测试数据,然后运行UPDATE STATISTICS Orders
。 DBCC SHOW_STATISTICS(Orders, PK__Orders__4F8C6988304CED14)
向我展示了这个结果:
现在,如果我运行查询
SELECT * FROM Orders WHERE BusinessUnit = 'USA'
其中一个步骤是按订单分组搜索,估计行数为735
但是,如果我添加像这样的Unicode转换
SELECT * FROM Orders WHERE BusinessUnit = N'USA'
我估计行数为410.5。
在进行Unicode转换时,导致估计行数变化的原因是什么?非Unicode字段上的索引是否可以与Unicode子句一起使用?当我有一些连接多个表的较大查询时,在WHERE子句中的单个字段上添加unicode转换会导致查询执行计划发生重大变化,这会使查询的运行时间增加一个数量级
答案 0 :(得分:1)
在SQL Server中,单个Unicode字符为16位,而非Unicode字符为8位。由于仅为表中的数据类型保留统计信息,因此没有将它们与Unicode值进行比较的良好统计信息。
当优化程序尝试优化varchar< ==>的查询时varchar查找,它使用统计信息来决定最佳查询计划,并估计返回的行数。
但是当它试图根据非varchar值查找varchar数据项时,它必须对不同数据类型如何影响平均查找进行有根据的猜测。我怀疑优化器会直接分析查找字符串中的值以查看当前非Unicode字符集中有多少,因此它可能使用一些预编程的统计值,基于哦,也许是您的默认字符集,也许您的国家/地区代码,用于确定将返回的行数的调整因子。
基本上,在将苹果与橘子进行比较并期待比赛时,您可能需要猜测一下预期的比赛次数。
答案 1 :(得分:1)
估算基于全密度而不是直方图,因为在编译时该值未知(由于隐式转换)。 All Density值为0.521 821行为410.5。