Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server、索引和参数的特殊情况_Sql_Sql Server_Indexing_Sql Execution Plan - Fatal编程技术网

SQL Server、索引和参数的特殊情况

SQL Server、索引和参数的特殊情况,sql,sql-server,indexing,sql-execution-plan,Sql,Sql Server,Indexing,Sql Execution Plan,我有一张桌子,我们称之为历史。主键(又名聚集索引)称为HIST\u ID。该表在开发数据库中大约有2300行。现在考虑以下两个查询: 问题1: declare @x int set @x = 14289 select * from History where hist_id=@x 问题2: declare @x int set @x = 14289 select * from History where hist_id=@x or @x is null 唯一的区别是结尾处的或@x为nul

我有一张桌子,我们称之为历史。主键(又名聚集索引)称为
HIST\u ID
。该表在开发数据库中大约有2300行。现在考虑以下两个查询:

问题1:

declare @x int
set @x = 14289

select * from History where hist_id=@x
问题2:

declare @x int
set @x = 14289

select * from History where hist_id=@x or @x is null
唯一的区别是结尾处的
或@x为null
。但是,第一个查询执行索引查找,第二个查询执行索引扫描。有什么好处

抢先回复-不,选项(重新编译)没有帮助


补充道:我想要一些确凿的论据,而不是猜测。我自己也能猜出十几个可能的原因。但是这里真正的问题是什么?

我想优化器认为这是有益的。另一种选择是使用与您编写的计划相同的计划

select * from History where hist_id=@x
union all
select * from History where @x is null
您可以用这种方式重写查询,但我非常确定优化器能够自己完成这项工作。您有多少个空值


编辑:原来我误读了这个问题,以为你想知道在哪里(@x=hist\u id或hist\u id为空)。事实上,您需要一个动态标准。退房请注意,如果指定WITH(重新编译),这种查询应该在SQL2k8中工作,但是由于一个严重的错误,这种支持被删除了。

我猜优化器认为这是有益的。另一种选择是使用与您编写的计划相同的计划

select * from History where hist_id=@x
union all
select * from History where @x is null
您可以用这种方式重写查询,但我非常确定优化器能够自己完成这项工作。您有多少个空值


编辑:原来我误读了这个问题,以为你想知道在哪里(@x=hist\u id或hist\u id为空)。事实上,您需要一个动态标准。退房请注意,如果您指定WITH(重新编译),这种查询应该在SQL2k8中工作,但由于一个严重的错误,此支持被删除。

我建议生成计划时与传入/使用的参数分开,因此本质上需要(取决于@x的值)返回每一行。因此,查询计划正在处理它可以接收的参数的最坏情况


e、 g.如果@x的输入为null,那么查询将被迫返回每一行,因为每一行都将满足一个总是返回true的文本等式/谓词。要使查询计划覆盖@x的每个值,它必须生成一个执行扫描的计划。

我建议该计划是与传入/使用的参数分开生成的,因此本质上有一个返回每一行的要求(取决于@x的值)。因此,查询计划正在处理它可以接收的参数的最坏情况

e、 g.如果@x的输入为null,那么查询将被迫返回每一行,因为每一行都将满足一个总是返回true的文本等式/谓词。要使查询计划覆盖@x的每个值,它必须生成一个执行扫描的计划。

当然是索引扫描

聚集索引扫描=表扫描,因为对“@x为NULL”没有合理的谓词

参数化、缓存的计划是通用的,适用于@x=NULL或@x=value。 如果你没有定义@x,你应该得到同样的计划

如果编码为“12345为空”,则会检测到并忽略此项

我找不到关于如何在查询计划中处理常量的博客文章。要点是它们是通用的,短路不允许计划重用。

当然这是索引扫描

聚集索引扫描=表扫描,因为对“@x为NULL”没有合理的谓词

参数化、缓存的计划是通用的,适用于@x=NULL或@x=value。 如果你没有定义@x,你应该得到同样的计划

如果编码为“12345为空”,则会检测到并忽略此项


我找不到关于如何在查询计划中处理常量的博客文章。要点是它们是通用的,短路不允许计划重用。

Ahem,仔细看!“is null”是针对@x完成的,而不是针对表!这是一个不断的错误表达!联合中的第二个SELECT语句将始终返回一个空集。@x的值是14289,不是空值。在发布累积更新5后,该支持被重新添加。如果你得到了最新的更新,那么它就会像广告上说的那样工作。啊哼,仔细看看!“is null”是针对@x完成的,而不是针对表!这是一个不断的错误表达!联合中的第二个SELECT语句将始终返回一个空集。@x的值是14289,不是空值。在发布累积更新5后,该支持被重新添加。如果你得到了最新的更新,那么它就会像广告上说的那样工作。我读到MSSQL可以做一些叫做“参数嗅探”的事情,这应该可以解决这个问题。选项(重新编译)实际上应该做到这一点,但事实并非如此。我确信,对于这个概念,有更多的技术描述使用了术语SARG,但这个版本更容易理解。参数嗅探功能试图将查询中的文本值转换为参数,因此有更多的查询计划缓存命中。您已经传入了一个参数,而不是一个文本,因此嗅探它不是问题/因此重新编译不会改变它。有时,执行计划可能会根据提供的参数值有很大差异。就像这件事一样。优化器应该知道这一点,并考虑这些值。在最坏的情况下,我可以指定选项(重新编译),根据文档,“使用查询中任何局部变量的当前值”。重新编译无关紧要,请删除参数,这样就没有嗅探,没有重新编译,使用literal语句,从hist_id=1或1为空的历史记录中选择*可进行扫描。重新编译是无关紧要的,当它将所有信息传递给它时,查询计划并没有让逻辑短路,正如我们所知,它应该能够做到的那样,引擎只是n