Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.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 Server 2005执行计划问题_Sql Server_Sql Execution Plan - Fatal编程技术网

Sql server SQL Server 2005执行计划问题

Sql server SQL Server 2005执行计划问题,sql-server,sql-execution-plan,Sql Server,Sql Execution Plan,目前,我在我们的应用程序中发现了一个查询,它的执行计划是索引扫描。下面是一些背景: 它有三列,类型为idType:bigint 手头只有200件物品 这里有一列a:PK,b:FK,c:FK,我们有两个索引,一个聚集索引x,c,一个PK非聚集索引a 以下是我们的疑问: exec sp_executesql N'select b,a from table where b in (@P0, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9)',

目前,我在我们的应用程序中发现了一个查询,它的执行计划是索引扫描。下面是一些背景:

它有三列,类型为idType:bigint 手头只有200件物品 这里有一列a:PK,b:FK,c:FK,我们有两个索引,一个聚集索引x,c,一个PK非聚集索引a 以下是我们的疑问:

exec sp_executesql N'select b,a from table where b in (@P0, @P1, @P2,
     @P3, @P4, @P5, @P6, @P7, @P8, @P9)',
     N'@P0 bigint, @P1 bigint, @P2 bigint, @P3 bigint, @P4 bigint, @P5 bigint,
       @P6 bigint, @P7 bigint, @P8 bigint, @P9 bigint', 
     94, 161, 4, 50, 166, 52, 53, 90, 100, 123
它从执行计划中显示为pk index上的索引扫描…出了什么问题

如果我使用相同的查询,但不使用sp_executesql,如:

select b,a from table where b in(94,161,4,50,166,52,53,90,100,123)
它显示了我所期望的聚集索引搜索

为什么SQL Server会对第一个查询使用索引扫描?它与功能有关吗 sp_executesql本身

谢谢你的支持
Vance

我在自己的数据库中查看了类似查询的执行计划,可以看到不同之处,但我无法完全解释;我只是觉得我的发现可能有用

这种差异似乎是由于在已编译的查询中使用了参数

在下面的示例中,我使用的是一个数据库中名为[Resource]的表,您必须更改查询的名称

正如您所发现的,在ManagementStudio中直接执行查询会导致索引搜索

使用带有参数的版本进行扫描

如果您完全准备好语句,然后将其传递给数据库,例如

exec('select id from [Resource] where id in (1,5,7,9,10)')
您再次获得索引搜索

有趣的是查看缓存的计划

SELECT cp.objtype,cp.usecounts,q.TEXT
FROM sys.dm_exec_cached_plans cp
 cross apply sys.dm_exec_query_plan(cp.plan_handle) p
 cross apply sys.dm_exec_sql_text(cp.plan_handle) AS q
WHERE cp.cacheobjtype = 'Compiled Plan'
对于我执行的三条语句

objtype usecounts text ------- --------- ---- Adhoc 1 select id from [Resource] where id in (1,5,7,9,10) Prepared 1 (@p1 int, @p2 int, @p3 int, @p4 int, @p5 int)select id from [Resource] where id in (@p1, @p2, @p3, @p4, @p5) Adhoc 1 select id from [Resource] where id in (1,5,7,9,10) 正如您所看到的,SQL是完全不同的。不幸的是,这就是我所能解释的索引选择的不同之处。也许其他人可以更进一步

编辑1:我读了更多的内容,归结到乐观主义者必须制定一个计划来满足所有可能的参数值,正如Kragen在他的回答中所说的

我在本文中发现了相同的信息:

编辑2:作为对Martin评论的回应,下面是他的SQL语句的执行计划


这种差异可能是由于在不同数据或不同参数意味着表扫描/索引查找是合适的时候执行了缓存查询计划。SQL命令文本本身是不同的,因此它们在计划缓存中都有不同的条目。如果要对此进行测试,可以使用以下命令清除计划缓存:

DBCC FREEPROCCACHE -- Don't run me on a production SQL server!
然后再次尝试运行这两个命令,看看是否仍然存在差异。如果您愿意挖掘计划缓存,则上述命令的某些版本是生产安全的


请注意,表扫描并不总是一件坏事,尤其是当表很窄并且没有太多行时,在您的示例中,情况就是这样。在这种情况下,表扫描可能比索引查找更有效。

实际的CREATE table和CREATE index语句比描述更容易理解。一般警告:如果删除了无关的列,如果表很宽,这个问题可以用columnsTry的一个子集在存储过程中执行代码来演示,看看执行计划是否与sp_execute或T-SQL计划相同会很有趣。这不一定能解决你的问题,我只是想得到更多的信息谢谢大家的回复@Tony我把第一个查询“exec sp_executesql N”。。。在SP中,并获得相同的索引扫描。这个问题是否与我的测试表值小有关?我只有大约200个条目,所以sql server不会优化它的查询执行吗?我想这可以归结为选择性。如果你从这里获得5个id,那么从[Resource]中选择top 5 id,COUNT*按id分组,order by COUNT*desc,并将它们作为文本进行尝试。你得到扫描还是搜索?@Martin:我发布了查询,但我想我误解了你试图实现的目标。是的,你得到了!假设您的查询显示5个最常见的id是100101102103104,我想知道您将从[Resource]中获得选择id的什么计划如果100101102103104中的id仍然为您提供了一个带有搜索的计划,那么我想不出任何理由支持参数化版本进行扫描,因为这应该是最坏的情况。@Martin-好的,我明白您的意思了。我确实尝试过从[Resource]中选择id,其中id在1,5,7,9,10中看到了执行寻道的第一个执行计划图像。我正在使用一些数据来测试查询,它与VanceZhao的数据不同。实际上,我们使用ibatis,上面的带有参数的查询就是从中生成的。是的,“从[Resource]中选择id,其中id在1,5,7,9,10中”将执行搜索,并且在“从[Resource]中选择id,其中id”下获取搜索in@a,@a,@a'但在查询时真正得到扫描'从[Resource]中选择id,其中idin@a,@b,@c