zoukankan      html  css  js  c++  java
  • 统计信息对执行计划的影响

    最近遇到一个问题,示例表结构如下:

    set statistics io on
    use tempdb 
    go
    --drop table TB
    create table TB (id int identity primary key, parentId int,name varchar(50))
    go
    insert into TB(parentId,name) select 0,CAST(NEWID() as varchar(50))
    go 499990
     
    insert into TB(parentId,name) select 499990,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499991,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499992,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499993,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499994,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499995,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499996,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499997,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499998,CAST(NEWID() as varchar(50))
    insert into TB(parentId,name) select 499999,CAST(NEWID() as varchar(50))
    go

    有一个如下的SQL查询:

    select * from TB 
    where parentId in (select id from TB where parentId=499997)

    速度非常的慢,明显是因为parentId字段无索引,然后,为其添加了索引:

    create index ix_parentId on TB(parentId)

    这时,清下执行计划缓存,再次执行该SQL查询,执行计划如下:

    DBCC FREEPROCCACHE 

    2011-10-27_140218

    看到有一个Clustered Index Scan ,这个是非常耗io的,而实事上parentId=499997的ID值只有一个,为499998,而parentId =499998的行也只有一条。
    IO扫描为:

    Table 'TB'. Scan count 10, logical reads 3882, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    这样看来,这个index scan非常的不合理。此时,我们看一下索引ix_parentid上的统计信息:
    2011-10-27_141843

    可以看到一共有500000行,采样为500000行,说明在建索引ix_parentid时,应该采用的是全扫描。

    接下来,单独执行了一次统计信息更新:

    UPDATE STATISTICS TB ix_parentId

    然后,再次查看统计信息:
    2011-10-27_142329

    此时,统计信息与之前不同,已不是全扫描,而是只采集了163584行,而且并未采集到parentid<>0的数据,再次清空执行计划缓存

    DBCC FREEPROCCACHE 

    然后执行本例的SQL查询,结果如下:

    2011-10-27_142501

    IO扫描为:
    Table 'TB'. Scan count 2, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    这样来看,执行计划已正常。

    在此案例中,由于parentid绝大多数值为0,只有极少数不为0,道理上来讲,并不应该创建索引,但实际业务中,也可能出现此类请求,何去何从?


    作者:nzperfect
    出处:http://www.cnblogs.com/nzperfect/
    引用或者转载本BLOG的文章请注明原作者和出处,并保留原文章中的版权信息。

  • 相关阅读:
    iconfont 引入后没有显示
    使用element-ui库时浏览器出现异常汉字(代码里找不到该汉字)
    ElementUI select 把整个option(对象)作为值
    不让浏览器history后退前进
    从IE浏览器链接跳转到谷歌浏览器方法
    mddir 可以生成项目工程结构
    Element-UI select 新加全部与多选互斥选择
    H5 video 常用属性
    a链接跳转报错 status为 canceled的解决办法
    学习计划与记录
  • 原文地址:https://www.cnblogs.com/nzperfect/p/2226510.html
Copyright © 2011-2022 走看看