mssql 如何查看“执行计划”

qingYun1029 2013-12-25 10:37:59
首先感谢一下“DBA_Huangzj”昨天不厌其烦的回答了我好多问题。

不过优化路漫漫,所以还是有一些疑问,所以再发一贴,请教各位数据库方面的大佬,不甚感激!

经过昨天的纠结得出两个结论:
1、用“SET STATISTICS IO ON”开启IO信息,如果 logical reads 数值越小,表示效率越高。
2、看执行计划,如果“预估IO开销”和“预估CPU开销”越小越好。

不知道这两点结论是否站得住脚?

现在问题来了,同一条sql语句,在有索引和无索引的情况下,执行计划显示的步骤有多有少的,如下图:
未建额外索引:


建立索引:create index test_index on dbo.Building_Queue(TileID)


从两张图中可以看出:将各不走开销百分比加起来都是 100%,

但是当将鼠标移到有开销的步骤上去,将各种情况下有开销的“IO开销”和“cpu开销”分别加起来这个是有差别的,那是不是说:将有开销的步骤的“io开销”和“cpu开销”分别累加起来,数值越小效率越高呢?

当然,还得看看 logical reads 的数值。
...全文
456 21 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
qingYun1029 2013-12-31
  • 打赏
  • 举报
回复
引用 20 楼 DBA_Huangzj 的回复:
[quote=引用 18 楼 qingYun1029 的回复:] 如下是存储过程的执行计划,实际的哦。
我还以为你结贴了,找不到你的贴,从图上来看,开销最大的是排序,其他的看不全,排序通常是order by、distinct、group by导致的,最直接的方法是使用聚集索引的预排序功能来减少,不过这往往在实际引用中很难完成。但是有时候非聚集索引也是可以实现的。总得来说: 1、先看看sql语句有没有改写的空间 2、看看索引是否设计合理 3、减少数据量,这样即使有排序操作,影响面也不大[/quote] 恩呢。谢谢啦!!
發糞塗牆 2013-12-25
  • 打赏
  • 举报
回复
虽然我们看性能很多时候看速度,但是sqlserver是基于开销的优化,所以开销低的绝大部分情况下是性能好点,但是也不排除其他影响因素
發糞塗牆 2013-12-25
  • 打赏
  • 举报
回复
加起来小于100或者超过100都是可能的,不过绝大部分时间是100,你要对比的话,两个查询放到一个界面看各自的百分比,如果是同一个查询,看set statics io/time on 这两个值,手僵,不写全了
  • 打赏
  • 举报
回复
至于执行计划如何读取,首先我们需要了解执行计划中的几个关键点: Rows:执行计划的每一步返回的实际行数 Executes:执行计划每一步被运行了多少次。 StmtText:执行计划的具体内容 EstimateRows:SQL Server根据表上的统计信息,预估算每一步返回的行数 EstimateIO:SQL Server根据EstimateRows和统计信息里记录的字段长度,预估每一不会产生的I/O开销 从这里我们可以看出,如果预估行数不准确了,那么EstimateIO也会受到影响 EstimateCPU:SQL Server根据EstimateRows和统计信息里记录的字段长度,以及要做的事情的复杂度预估算每一步会产生的CPU Cost. TotalSubtreeCost:SQL Server根据EstimateIO和EstimateCPU计算出来的没不执行计划 子树的Cost(包括这一步自己的开销和它的所有下层不走的cost总和)
qingYun1029 2013-12-25
  • 打赏
  • 举报
回复
引用 12 楼 TravyLee 的回复:
1、SET STATISTICS IO ON 2、看执行计划,如果“预估IO开销”和“预估CPU开销”越小越好。 为什么要开启SET STATISTICS IO ON?因为通过开启它我们可以看看执行某条语句时是否做了过多的I/O读取。 如果一条居于需要访问的数据页没有事先缓存在内存里,那么在执行过程中就必须从磁盘读到内存里。这个也就是说的physical reads和read-ahead reads. 一个查询语句从磁盘读取页数就是physical reads+read-ahead reads的结果。这个结果越小越好,毕竟每次查询都从磁盘读数据是很昂贵的。 logical reads也就是所谓的逻辑读取。他是从数据缓存读取的数据的页数。如果一个查询logical reads的结果越大,说明内存消耗量也就越大,查询也就越昂贵。这个时候可以考虑调整索引,较小扫描次数,缩小扫描范围
嗯嗯。谢谢你的解释!!
  • 打赏
  • 举报
回复
1、SET STATISTICS IO ON 2、看执行计划,如果“预估IO开销”和“预估CPU开销”越小越好。 为什么要开启SET STATISTICS IO ON?因为通过开启它我们可以看看执行某条语句时是否做了过多的I/O读取。 如果一条居于需要访问的数据页没有事先缓存在内存里,那么在执行过程中就必须从磁盘读到内存里。这个也就是说的physical reads和read-ahead reads. 一个查询语句从磁盘读取页数就是physical reads+read-ahead reads的结果。这个结果越小越好,毕竟每次查询都从磁盘读数据是很昂贵的。 logical reads也就是所谓的逻辑读取。他是从数据缓存读取的数据的页数。如果一个查询logical reads的结果越大,说明内存消耗量也就越大,查询也就越昂贵。这个时候可以考虑调整索引,较小扫描次数,缩小扫描范围
LongRui888 2013-12-25
  • 打赏
  • 举报
回复
引用 10 楼 qingYun1029 的回复:
[quote=引用 7 楼 yupeigu 的回复:] [quote=引用 4 楼 qingYun1029 的回复:] [quote=引用 2 楼 yupeigu 的回复:] 最好这样,你把两个语句,放到一起执行,会显示 这2个查询,分别占用了 多少开销,比如这样:
哈哈哈哈,又是你,谢谢啦! 这是个不错的办法,可以用来判断相同目标的sql语句不同的写法。 不过对于同一条sql语句,只是有关于有没有索引的情况下这种办法用不了。[/quote] 可以的,不过因为你的语句是update语句,会有点问题,把你的update语句改成 select语句,强制使用索引就可以:
--强制用 PK_BUILDING_QUEUE 索引
select titleID
from building_queue with(index (PK_BUILDING_QUEUE))
where titleID = 1002


--强制用 test_index 索引
select titleID
from building_queue with(index (test_index))
where titleID = 1002

[/quote] 改用select可以看出update语句的效率么?[/quote] 嗯,因为,update语句也是先select 查找到数据,然后再进行update的。
qingYun1029 2013-12-25
  • 打赏
  • 举报
回复
引用 7 楼 yupeigu 的回复:
[quote=引用 4 楼 qingYun1029 的回复:] [quote=引用 2 楼 yupeigu 的回复:] 最好这样,你把两个语句,放到一起执行,会显示 这2个查询,分别占用了 多少开销,比如这样:
哈哈哈哈,又是你,谢谢啦! 这是个不错的办法,可以用来判断相同目标的sql语句不同的写法。 不过对于同一条sql语句,只是有关于有没有索引的情况下这种办法用不了。[/quote] 可以的,不过因为你的语句是update语句,会有点问题,把你的update语句改成 select语句,强制使用索引就可以:
--强制用 PK_BUILDING_QUEUE 索引
select titleID
from building_queue with(index (PK_BUILDING_QUEUE))
where titleID = 1002


--强制用 test_index 索引
select titleID
from building_queue with(index (test_index))
where titleID = 1002

[/quote] 改用select可以看出update语句的效率么?
LongRui888 2013-12-25
  • 打赏
  • 举报
回复
引用 6 楼 qingYun1029 的回复:
[quote=引用 3 楼 yupeigu 的回复:] 那个绝对的开销数据,意义不是很大。 另外,就像你看到的,96%+3%=99% 不到100%,还有开销可能都是小于1%的,他可能就显示出来。 还有,一般,通过把2个查询,放到一起,就像上面那样,倒是可以比较2个查询,分别占用了多少开销的,开销大的,想到性能就低了
绝对开销就是么? 其实大部分把那个“绝对开销”加起来都是百分之百,如果在百分之百的情况下怎么比较呢?[/quote] 其实这个100%,只是对于某一个语句而言的,而且这个具体的开销值,也不一定是准确的
qingYun1029 2013-12-25
  • 打赏
  • 举报
回复
引用 5 楼 yupeigu 的回复:
另外,从你贴的图,可以看出第一个图的开销在,聚集索引扫描上,而第二个图的开销,在于聚集索引的更新上,这个开销和你新建了1个索引有关。 不过总体上来看,应该还是建了索引的,效率更高。
怎么怎么看出来的呢?
LongRui888 2013-12-25
  • 打赏
  • 举报
回复
引用 4 楼 qingYun1029 的回复:
[quote=引用 2 楼 yupeigu 的回复:] 最好这样,你把两个语句,放到一起执行,会显示 这2个查询,分别占用了 多少开销,比如这样:
哈哈哈哈,又是你,谢谢啦! 这是个不错的办法,可以用来判断相同目标的sql语句不同的写法。 不过对于同一条sql语句,只是有关于有没有索引的情况下这种办法用不了。[/quote] 可以的,不过因为你的语句是update语句,会有点问题,把你的update语句改成 select语句,强制使用索引就可以:
--强制用 PK_BUILDING_QUEUE 索引
select titleID
from building_queue with(index (PK_BUILDING_QUEUE))
where titleID = 1002


--强制用 test_index 索引
select titleID
from building_queue with(index (test_index))
where titleID = 1002

qingYun1029 2013-12-25
  • 打赏
  • 举报
回复
引用 3 楼 yupeigu 的回复:
那个绝对的开销数据,意义不是很大。

另外,就像你看到的,96%+3%=99% 不到100%,还有开销可能都是小于1%的,他可能就显示出来。

还有,一般,通过把2个查询,放到一起,就像上面那样,倒是可以比较2个查询,分别占用了多少开销的,开销大的,想到性能就低了


绝对开销就是么?

其实大部分把那个“绝对开销”加起来都是百分之百,如果在百分之百的情况下怎么比较呢?
LongRui888 2013-12-25
  • 打赏
  • 举报
回复
另外,从你贴的图,可以看出第一个图的开销在,聚集索引扫描上,而第二个图的开销,在于聚集索引的更新上,这个开销和你新建了1个索引有关。 不过总体上来看,应该还是建了索引的,效率更高。
qingYun1029 2013-12-25
  • 打赏
  • 举报
回复
引用 2 楼 yupeigu 的回复:
最好这样,你把两个语句,放到一起执行,会显示 这2个查询,分别占用了 多少开销,比如这样:
哈哈哈哈,又是你,谢谢啦! 这是个不错的办法,可以用来判断相同目标的sql语句不同的写法。 不过对于同一条sql语句,只是有关于有没有索引的情况下这种办法用不了。
LongRui888 2013-12-25
  • 打赏
  • 举报
回复
那个绝对的开销数据,意义不是很大。 另外,就像你看到的,96%+3%=99% 不到100%,还有开销可能都是小于1%的,他可能就显示出来。 还有,一般,通过把2个查询,放到一起,就像上面那样,倒是可以比较2个查询,分别占用了多少开销的,开销大的,想到性能就低了
LongRui888 2013-12-25
  • 打赏
  • 举报
回复
最好这样,你把两个语句,放到一起执行,会显示 这2个查询,分别占用了 多少开销,比如这样:

qingYun1029 2013-12-25
  • 打赏
  • 举报
回复
引用 楼主 qingYun1029 的回复:
首先感谢一下“DBA_Huangzj”昨天不厌其烦的回答了我好多问题。 不过优化路漫漫,所以还是有一些疑问,所以再发一贴,请教各位数据库方面的大佬,不甚感激! 经过昨天的纠结得出两个结论: 1、用“SET STATISTICS IO ON”开启IO信息,如果 logical reads 数值越小,表示效率越高。 2、看执行计划,如果“预估IO开销”和“预估CPU开销”越小越好。 不知道这两点结论是否站得住脚? 现在问题来了,同一条sql语句,在有索引和无索引的情况下,执行计划显示的步骤有多有少的,如下图: 未建额外索引: 建立索引:create index test_index on dbo.Building_Queue(TileID) 从两张图中可以看出:将各不走开销百分比加起来都是 100%, 但是当将鼠标移到有开销的步骤上去,将各种情况下有开销的“IO开销”和“cpu开销”分别加起来这个是有差别的,那是不是说:将有开销的步骤的“io开销”和“cpu开销”分别累加起来,数值越小效率越高呢? 当然,还得看看 logical reads 的数值。
好像第一张图片不是100% 不过好像大部分都是100%的
發糞塗牆 2013-12-25
  • 打赏
  • 举报
回复
引用 18 楼 qingYun1029 的回复:
如下是存储过程的执行计划,实际的哦。
我还以为你结贴了,找不到你的贴,从图上来看,开销最大的是排序,其他的看不全,排序通常是order by、distinct、group by导致的,最直接的方法是使用聚集索引的预排序功能来减少,不过这往往在实际引用中很难完成。但是有时候非聚集索引也是可以实现的。总得来说: 1、先看看sql语句有没有改写的空间 2、看看索引是否设计合理 3、减少数据量,这样即使有排序操作,影响面也不大
Leon_He2014 2013-12-25
  • 打赏
  • 举报
回复
楼主把sql语句贴出来吧,不然怎么优化
qingYun1029 2013-12-25
  • 打赏
  • 举报
回复
如下是存储过程的执行计划,实际的哦。
加载更多回复(1)

34,837

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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