设为首页 收藏本站
查看: 774|回复: 0

[经验分享] 浅析SQL SERVER执行计划中的各类怪相

[复制链接]

尚未签到

发表于 2015-6-27 11:12:48 | 显示全部楼层 |阅读模式
  在查看执行计划或调优过程中,执行计划里面有些现象总会让人有些疑惑不解:
      1:为什么同一条SQL语句有时候会走索引查找,有时候SQL脚本又不走索引查找,反而走全表扫描?
      2:同一条SQL语句,查询条件的取值不同,它的执行计划会一致吗?
      3: 同一条SQL语句,其执行计划会变化,为什么
      4: 在查询条件的某个或几个字段上创建了索引,执行计划就一定会走该索引吗?
      5:同时存在几个索引,SQL语句会走那个索引?
       ............................................................
  有时候如果要跟别人解释清楚这些问题,如果不通过一些案例或例子来解说,很难阐述清楚,一方面是表达能力问题。另外一方面,再华丽的语言也难敌眼见为实,毕竟人接受信息大部分通过眼睛,小部分通过耳朵。眼见为实耳听为虚吗!  下面来看一个简单的例子,为什么我在对应的查询字段上建有索引,但是它不走索引反而走全表扫描。


DROP TABLE TEST    CREATE TABLE TEST (OBJECT_ID  INT, NAME VARCHAR(8));    CREATE INDEX PK_TEST ON TEST(OBJECT_ID)    DECLARE @Index INT =0; WHILE @Index < 20BEGIN    INSERT INTO TEST    SELECT @Index, 'kerry';        SET @Index = @Index +1;END  UPDATE STATISTICS TEST WITH FULLSCAN SELECT * FROM TEST WHERE OBJECT_ID=1  
   DSC0000.png
  
  已经在查询字段OBJECT_ID上建立了索引,为什么SQL优化器不走索引,而要走全表扫描呢?为了说明白,那么我们借助于查询提示(Hints)强制优化器走索引查找来说明上述情况,对比走索引查找、全表扫描两者的代价开销,从下图,我们可以看到当前情况下,走全表扫描的开销要小于索引查找。因为当前情况下,走索引需要额外的IO开销,反而不如全表扫描。所以优化器选择了走全表扫描而非索引查找。很多开发人员有种根深蒂固的固执观念“走索引查找一定要优于全表扫描”(我跟他们解释的时候,很多人不相信,"慷慨激昂"的质疑我,以至于我的解释都显得苍白无力),大多数情况下,走索引查找要优于全表扫描,但是在特定的场景、特定数据情况下,会出现全表扫描优于索引查找的情况。尤其是ORACLE里面,很多做开发的同事一看到SQL执行计划走全表扫描,立马大呼小叫。其实完全是先入为主的观念作怪。




SELECT * FROM TEST WHERE OBJECT_ID=1  SELECT * FROM TEST WITH(INDEX=PK_TEST) WHERE OBJECT_ID =1   
   DSC0001.png

    两者开销不一致,其实在IO开销这一块,可以从下面看出逻辑读取的差异。




DBCC FREEPROCCACHE;DBCC DROPCLEANBUFFERS;SET STATISTICS IO ON; SELECT * FROM TEST WHERE OBJECT_ID=1  
  
   DSC0002.png
  




DBCC FREEPROCCACHE; DBCC DROPCLEANBUFFERS; SET STATISTICS IO ON; SELECT * FROM TEST WITH(INDEX=PK_TEST) WHERE OBJECT_ID =1   
  
   DSC0003.png

  
    那么接下来,我们将该表的数据从20条记录增长到10000条记录,你觉得执行计划会变化吗?大家不妨先思考一下这个问题,再看下文。




TRUNCATE TABLE TEST;DECLARE @Index INT =0; WHILE @Index < 10000BEGIN    INSERT INTO TEST    SELECT @Index, 'kerry';        SET @Index = @Index +1;END  UPDATE STATISTICS TEST WITH FULLSCANSELECT * FROM TEST WHERE OBJECT_ID=1
  
  如下所示,当数据变化时,优化器认为走索引查找要优于全表扫描,所以选择了索引查找,说到底优化器是基于成本的优化器,在众多的执行计划中,它会选择代价开销最小的一个执行计划。
  
   DSC0004.png
  
  此时,强制优化器走全表扫描,对比开销结果,你会发现结果完全跟上面结果相反。
  
   DSC0005.png
    我如果更新该表数据,使其分布完全倾斜,那么你可以看到对于同一个SQL,不同的取值,它的执行计划也会完全不同。




UPDATE TEST SET OBJECT_ID =1 WHERE OBJECT_ID='2013-07-09 00:00'   AND CREATE_DATE ='2013-07-09 00:00'   AND CREATE_DATE ='2013-04-09 00:00'   AND CREATE_DATE ='2013-04-09 00:00'   AND CREATE_DATE ='2013-04-09 00:00'   AND CREATE_DATE ='2013-04-09 00:00'   AND CREATE_DATE

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-80898-1-1.html 上篇帖子: SQL Server 中 RAISERROR 的用法 下篇帖子: SQL Server 2008中的新日期数据类型
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表