SQL Server 的查询优化器是基于开销的。这意味着它将选择执行具有最低估计处理开销的查询计划。查询优化器基于以下两个主要因素来确定执行查询计划的开销:
- 查询计划每个级别上处理的总行数,称为该计划的基数。
- 由查询中所使用的运算符规定的算法的开销模式。
第一个因素(基数)用作第二个因素(开销模式)的输入参数。因此,增大基数将减少估计开销,从而加快执行计划。
SQL Server 主要从创建索引或统计信息时创建的直方图手动或自动估计基数。有时,SQL Server 还使用查询的约束信息和逻辑重写来确定基数。
在下列情况下,SQL Server 无法精确计算基数。这将使开销计算不准确,可能导致生成不理想的查询计划。避免在查询中使用这些构造可以提高查询性能。有时,使用查询表达式或其他措施也可以提高查询性能,如下所述:
- 带谓词的查询,这些查询在同一表的不同列之间使用比较运算符。
- 带谓词的查询,这些查询使用运算符且下列任何一种情况为 True:
- 运算符两侧所涉及的列中没有统计信息。
- 统计信息中值的分布不均匀,但查询将查找高选择性的值集。特别是,当运算符是除相等 (=) 运算符以外的任何其他运算符时,这种情况可能为 True。
- 谓词使用不等于 (!=) 比较运算符或 NOT 逻辑运算符。
- 使用 SQL Server 内置函数、标量值函数或用户定义的函数(其参数不是常量值)的查询。
- 包含通过算术或字符串串联运算符联接的列的查询。
- 比较在编译或优化查询时其值未知的变量的查询。
下列措施可用于尝试提高这些类型的查询的性能:
如果查询使用比较或算术运算符比较或组合两个或多个列,则考虑使用计算列并重写查询。例如,以下查询比较两列中的值:
SELECT * FROM MyTable WHERE MyTable.Col1 > MyTable.Col2如果将计算列 Col3 添加到用于计算 Col1 和 Col2 之间的差(即 Col1 减去 Col2)的 MyTable,可能会提高性能。然后,重写查询:
SELECT * FROM MyTable WHERE Col3 > 0如果对 MyTable.Col3 生成索引,则性能可能会有更大的提高。