Dua*_*ane 7 sql-server optimization
我正在探索 SQL Server 中的优化器,特别是直方图,我看到了一些奇怪的结果。
如果我执行下面的查询,我知道字段上没有直方图,SQL Server 会输出一个行估计值,等于实际结果。如果我要在我使用的地方运行相同的查询DECLARE @i NUMERIC(19,2) = 30.0而不是常量WHERE [Rate] < @i,那么估计值94.8与我对显示的查询的期望一样,因为数据库没有关于该字段的统计信息。
所以我的问题是为什么 SQL Server 在没有该字段的统计信息时输出正确的结果?
当AUTO_CREATE_STATISTICS按照我的回答所示关闭时,我在行估计中遇到了一些奇怪的行为。
表上存在一个约束,限制[Rate]在 之间6.5 - 200.0。估计取决于如果在实验时有很大的差异>,使用或>=以及24.0或64格式的查询,其中谓词表示隐式转换输入money。
对于WHERE [Rate] > 6.5估计值28.44,然后以高于 的速率停止100。
对于WHERE [Rate] > 7排除小数的地方,28.44估计一直运行到255
对于WHERE [Rate] >= 6.5该28.44估算使用长达约100然后改到17.7764多达1000之前估计下降到1。
所以似乎没有太多的一致性。似乎 SQL Server 知道基于我正在试验的一些查询的约束,但它有时也会忽略它的存在。
Pau*_*ite 13
首先,如您所见,如果数据库选项AUTO_CREATE_STATISTICS打开,SQL Server 将在编译执行计划时自动创建丢失的统计信息(在可能的情况下)。
当统计数据不可用时,未知不等式谓词的默认猜测为 0.3 (30%)。使用局部变量时,不能嗅探变量中的值(除非OPTION (RECOMPILE)也指定了)。表基数为 316 时,估计值为 0.3 * 316 = 94.8。
当您使用常量文字时,会嗅探该值。没有统计数据,它不能像往常一样使用这个嗅探值来检查直方图,但它可以判断它对CHECK约束的影响(将 Rate 值限制在 $6.50 和 $200 之间)。
如果嗅探值不排除检查约束范围完全,估计是基于0.09(9%)为猜中的选择性BETWEEN谓词(来自校验约束)。316 * 0.09 = 28.44。
如果嗅探值确实完全排除了检查约束范围,则估计值始终为 1 行(基数估计器(几乎)从不产生小于 1 的估计行数)。
如果查询足够简单以符合简单计划的条件,并且对于简单参数化被认为是安全的,则常量文字将替换为参数标记,例如@1。这发生在如下查询中:
SELECT *
FROM HumanResources.EmployeePayHistory AS EPH
WHERE EPH.Rate > $200;
Run Code Online (Sandbox Code Playgroud)
执行计划显示估计为 1 行:
并且 Scan Predicate 显示了一个参数标记:
如果简单的参数化被阻止,例如通过添加一个比较常量和常量的子句:
SELECT *
FROM HumanResources.EmployeePayHistory AS EPH
WHERE EPH.Rate > $200
AND 1 = 1;
Run Code Online (Sandbox Code Playgroud)
如果没有参数化,这个计划永远不能用参数的不同值重用,因此优化器可以静态地消除表访问,因为检查约束阻止了任何行的返回。复工计划是:
最后,注意类型。Rate 列的类型是货币,而不是小数。转换可以以复杂的方式影响基数估计。使用 $ 前缀指定货币文字,或使用显式CAST或CONVERT.
基数估计的内部细节没有公开记录(可能是为了避免在事情发生变化时无休止的更详细的问题和抱怨),但是有一系列资源可以在这方面为您提供帮助。请记住,其中大部分内容都是非官方的,因此不受任何人的支持。有些方面实际上是危险的。
有些仅适用于原始(2014 年之前)基数估计器,有些解释了适用于两者的一般原则,有些仅适用于“新”CE。以下并非权威或完整列表,只是立即想到的列表:
| 归档时间: |
|
| 查看次数: |
500 次 |
| 最近记录: |