微软自动选择最优的计划吗?

zhengnan2012 2012-12-06 11:19:22

大侠们好,不是说 sqlserver自动选择最优化的方案执行吗?
看下面情况
select * from ta a join tb b on a.c1=b.c1 join tx c on b.c2=c.c2
where a.c3 between '2' and '8'
-- and b.c3 between '2' and '8'
ta(c1,c2,c3) c3上聚集索引
tb(c1,c2,c3) c3上聚集索引 c2上非聚集索引
tx(c2) 无索引
其中 a.c3也 b.c3的内容完全一样对应的。

b与c联接操作时,可能用到c2上的索引,也可能用到条件里的b.c3上 但是我发现sqlserver只要加上了c3列它就会自动用聚集索引,如果数据分布按一定的格式,这样反而更慢了?
这是什么情况必须自己注意吗?如果数据变动了,又有可能加上条件更好。sqlserver不能自动选择最优的方案吗?
...全文
183 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
专注or全面 2012-12-07
  • 打赏
  • 举报
回复
引用 11 楼 zhengnan2012 的回复:
请看,4楼下面的两个执行计划,都用到了b.c3,也就是聚集索引列,那么执行计划都会用到聚储索引,就是很费时也会选择它。 我自己是用的大数据做的实验证,就算相差几分钟,sqlserver也会选这个耗时的。 那以后我们写条件是不是要注意到了?
早上上班没时间回帖,我不知道你是怎么测试的,相差几分钟,sqlserver也会选择耗时的 能不能贴出表结构,表数据量,执行计划? 另外我看不懂4楼贴的执行计划是干嘛的 有索引,查询时候用索引,哪里有错???
zoffor 2012-12-07
  • 打赏
  • 举报
回复
对了 2008 可以强制index seek
zoffor 2012-12-07
  • 打赏
  • 举报
回复
因为会重用第一次执行的计划 这种问题确实麻烦 在不同的数据分布下 会使用旧的执行计划 我也很头疼 可以考虑用 recompile 或者 optimize for
zhengnan2012 2012-12-06
  • 打赏
  • 举报
回复

--大侠们好,不是说 sqlserver自动选择最优化的方案执行吗?看下面情况
select * from ta a join tb b on a.c1=b.c1 join tx c on b.c2=c.c2
where a.c3 between '2' and '8'
-- and b.c3 between '2' and '8'
/*
ta(c1,c2,c3) c3上聚集索引
tb(c1,c2,c3) c3上聚集索引 
c2上非聚集索引tx(c2) 无索引
其中 a.c3也 b.c3的内容完全一样对应的。 
b与c联接操作时,可能用到c2上的索引,也可能用到条件里的b.c3上 
但是我发现sqlserver只要加上了c3列它就会自动用聚集索引,如果数据分布按一定的格式,这样反而更慢了?
这是什么情况必须自己注意吗?如果数据变动了,又有可能加上条件更好。sqlserver不能自动选择最优的方案吗?
*/ 
zhengnan2012 2012-12-06
  • 打赏
  • 举报
回复

--大侠们好,不是说 sqlserver自动选择最优化的方案执行吗?看下面情况
select * from ta a join tb b on a.c1=b.c1 join tx c on b.c2=c.c2
where a.c3 between '2' and '8'
-- and b.c3 between '2' and '8'
/*
ta(c1,c2,c3) c3上聚集索引
tb(c1,c2,c3) c3上聚集索引 
c2上非聚集索引tx(c2) 无索引
其中 a.c3也 b.c3的内容完全一样对应的。 b与c联接操作时,可能用到c2上的索引,也可能用到条件里的b.c3上 但是我发现sqlserver只要加上了c3列它就会自动用聚集索引,如果数据分布按一定的格式,这样反而更慢了?这是什么情况必须自己注意吗?如果数据变动了,又有可能加上条件更好。sqlserver不能自动选择最优的方案吗?
*/
Andy-W 2012-12-06
  • 打赏
  • 举报
回复
引用 11 楼 zhengnan2012 的回复:
请看,4楼下面的两个执行计划,都用到了b.c3,也就是聚集索引列,那么执行计划都会用到聚储索引,就是很费时也会选择它。 我自己是用的大数据做的实验证,就算相差几分钟,sqlserver也会选这个耗时的。 那以后我们写条件是不是要注意到了?
當SQL Server 無法選擇最優的方案,你可以指定具體的索引來提高查詢效率。但有些時候反而會降低查詢效率,需要自己評估實際的數據來選擇。
zhengnan2012 2012-12-06
  • 打赏
  • 举报
回复
请看,4楼下面的两个执行计划,都用到了b.c3,也就是聚集索引列,那么执行计划都会用到聚储索引,就是很费时也会选择它。 我自己是用的大数据做的实验证,就算相差几分钟,sqlserver也会选这个耗时的。 那以后我们写条件是不是要注意到了?
zhengnan2012 2012-12-06
  • 打赏
  • 举报
回复
可能是我没有说清楚问题,我说的是这样的,大有一定数据量下,只要有聚集索引的条件,就算十分的费时,那sqlserver也会选择它。这种情况怎么处理?
专注or全面 2012-12-06
  • 打赏
  • 举报
回复
所以说执行计划是选择尽可能最优的 不是说为了找到最优的执行计划,不惜一些代价 就像你去县城,最远的路程需要1小时,你不会花2小时去为了找一个最近的路程吧?
专注or全面 2012-12-06
  • 打赏
  • 举报
回复
好像是这样的 假如啊,假如: 查找了100个执行计划,耗时1秒 这100个计划中有一个计划的执行时间是1秒 那么,还有必要继续找下去吗
發糞塗牆 2012-12-06
  • 打赏
  • 举报
回复
由于编译和生成执行计划的过程非常耗时并且有些时候会出现无法预知的备用方案,所以SQLServer到一定的阈值,就会停止生成执行计划,此时的执行计划就可能不是真正最优的。改变索引、改变数据、改变架构等等都会导致执行计划重新生成。
發糞塗牆 2012-12-06
  • 打赏
  • 举报
回复
所谓的自动并不是绝对的,不然就不需要出现hints,由于数据量、统计信息、编写的思路等等,都会使得SQLServer选取的所谓的最优执行计划有所偏离甚至选择了一个非常差的执行计划。
guguda2008 2012-12-06
  • 打赏
  • 举报
回复
没人这么说过,MSSQL只是从数个可行的执行计划中挑一个而已
Andy-W 2012-12-06
  • 打赏
  • 举报
回复
e.g.
use tempdb
go
if object_id('ta') Is not null Drop Table ta
if object_id('tb') Is not null Drop Table tb
if object_id('tx') Is not null Drop Table tx
create table ta(c1 nvarchar(50),c2 nvarchar(50),c3 nvarchar(50));create clustered index ix_ta_c3 on ta(c3);create index ix_ta_c2 on ta(c2);
create table tb(c1 nvarchar(50),c2 nvarchar(50),c3 nvarchar(50));create clustered index ix_tb_c3 on tb(c3);create index ix_tb_c2 on tb(c2);
create table tx(c1 nvarchar(50),c2 nvarchar(50),c3 nvarchar(50));
go
insert into ta(c1,c2,c3) values
('1','2','3'),
('2','3','4'),
('3','4','5'),
('4','5','6'),
('5','6','7');
insert into tb(c1,c2,c3) values
('1','2','3'),
('2','3','4'),
('3','4','5'),
('4','5','6'),
('5','6','7');
insert into tx(c1,c2,c3) values
('1','2','3'),
('2','3','4'),
('3','4','5'),
('4','5','6'),
('5','6','7');



--1
select *
from ta a
join tb b on a.c1 = b.c1
join tx c on b.c2 = c.c2
where a.c3 between '2' and '8'



--2
select *
from ta a
join tb b on a.c1 = b.c1
join tx c on b.c2 = c.c2
where a.c3 between '2' and '8'
and b.c3 between '1' and '1'



--3
select *
from ta a
join tb b on a.c1 = b.c1
join tx c on b.c2 = c.c2
where a.c3 between '2' and '8'
and b.c3 between '2' and '8'


Andy-W 2012-12-06
  • 打赏
  • 举报
回复
SQL Server是根據查詢的條件和數據量的大小來選擇對應的執行計劃。

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧