因为 where uid=@uid 使用的变量,分析成本时,并不计算变量值,无法估计uid可能出现在哪个表,所以先在各个表中预描。而 where uid=10 时,因为分区视图创建时确定了边界值,因此会确定扫描范围。
你是问在简单语句中,还是存储过程中?存储过程中,被编译的和被缓存的计划只是指可以被确定的东西。可能一些概念说不太清。 create proc as ... exec(@s) go它编译的就是里面的语句体,而@s执行的是什么,只有运行中编译,@s里的语句是没有编译和计划缓存的。对于你的分区视图一样的,即使在存储过程中,也是一样的道理,存储过程执行时,它只知道是 select * from v where uid=@uid 至于怎么扫描,仍未确定。我的意思并不是说,当这样的查询语句加入存储过程后,就能确定它扫哪个表了。
楼上朋友意思是,即使是在存储过程,执行下面语句, declare @uid = 10 select * from A where uid = @uid 也会扫描所有子表.再问,那么我使用动态语句,这样来执行呢? declare @uid = 10 declare @sqlStr varchar(8000) set @sqlStr = ' select * from A where uid = ' + str(@uid ) exec(@sqlStr) 这样,是不是让编译器执行前就认定了uid的确定值,而只会去扫描一个表了?
使用的变量,分析成本时,并不计算变量值,无法估计uid可能出现在哪个表,所以先在各个表中预描。而 where uid=10 时,因为分区视图创建时确定了边界值,因此会确定扫描范围。
create proc
as
... exec(@s)
go它编译的就是里面的语句体,而@s执行的是什么,只有运行中编译,@s里的语句是没有编译和计划缓存的。对于你的分区视图一样的,即使在存储过程中,也是一样的道理,存储过程执行时,它只知道是 select * from v where uid=@uid
至于怎么扫描,仍未确定。我的意思并不是说,当这样的查询语句加入存储过程后,就能确定它扫哪个表了。
declare @uid = 10
select *
from A
where uid = @uid
也会扫描所有子表.再问,那么我使用动态语句,这样来执行呢?
declare @uid = 10
declare @sqlStr varchar(8000)
set @sqlStr = '
select *
from A
where uid = ' + str(@uid )
exec(@sqlStr)
这样,是不是让编译器执行前就认定了uid的确定值,而只会去扫描一个表了?
那么是不是在存储过程中,多使用exec(@sqlStr) 的方式来执行查询语句,反而效率更高呢?
当然生成查询字符串也要消耗一定资源,但我认为字符串的处理应该非常快,可以忽略不计.
在存储过程中对"分区视图"进行查询时,一定要先生成字符串查询语句,使得查询
条件中的变量变成确定值,然后用exec()的方式来执行.当然,这时无法将查询结果生成中间变量了.