永東ID:N_chow
657次访问,排名2万外好友0人,关注者1
N_chow的文章
原创 2 篇
翻译 0 篇
转载 0 篇
评论 2 篇
最近评论
ju_feng:好文章啊,怎么没有继续呢?

怎么也想不明白是用了Clustered Index Scan
是VarDate 数据 20060801的数据比较多,
记得None Clustered Index 选取度在5%下用

但是为什么用了Clustered Index Scan?
N_chow:郁闷,文章内容怎么不出来呢??
文章分类
    收藏
      相册
      存档
      软件项目交易
      订阅我的博客
      XML聚合  FeedSky
      订阅到鲜果
      订阅到Google
      订阅到抓虾
      订阅到BlogLines
      订阅到Yahoo
      订阅到GouGou
      订阅到飞鸽
      订阅到Rojo
      订阅到newsgator
      订阅到netvibes

      原创 要我怎么相信你?-----浅谈SQL Server执行计划对索引的选择收藏

       | 旧一篇: Welcome!

       

       

      有这样一个需求,系统中有个库存异动明细表(tblStockVar) ,给出一个日期,需要计算从当前日期倒推到该日期的库存数。库存异动明细表很大,每天都以几百笔的资料在增加,表结构像这个样子(序(自动增长列), 功能别,仓库别,材料,储位,材料批号,异动日期,异动良品数,异动不良数,当前库存良品数,当前库存不良数)

      於是有这以下SQL查询在给出日期之后总的库存异动数.

      SELECT  WHCode , LocoID  , PartCode  , LotNo  , Sum ( VarStockQty  ) AS VarStockQty  , Sum ( VarBadQty  ) AS VarBadQty 
      FROM  tblStockVar  
      WHERE   VarDate   > 20060801
      GROUP BY WHCode , LocoID  , PartCode  , LotNo

      tblStockVar中VarDate上建有索引( IX_tblStockVar_VarDate), 一个复合索引( WHCode,LocoID,PartCode,LotNo),PK是SortKey(序) 栏位, 并且是Clustered Unique 一的个INDEX。

      按我们的理解,以上SQL应该要用到索引IX_tblStockVar_VarDate, 对此索引查找后再来一个Bookmark Lookup,搜寻到对应的其它字段资料,然后再汇总。但在实际应用中,该语句经常要执行60秒左右,显然没有用到索引.来看一下执行计划.
      用set statistics profile on 输出以下结果.

        |--Hash Match(Aggregate, HASH:([tblStockVar].[WHCode], [tblStockVar].[LocoID], [tblStockVar].[PartCode], [tblStockVar].[LotNo]), RESIDUAL:((([tblStockVar].[WHCode]=[tblStockVar].[WHCode] AND [tblStockVar].[LocoID]=[tblStockVar].[LocoID]) AND [tblStockVar
             |--Clustered Index Scan(OBJECT:([CustDB].[dbo].[tblStockVar].[PK_tblStockVar]), WHERE:([tblStockVar].[VarDate]>20060801))
      很明显,这里使用了一个Clustered Index Scan,而不是我们想的Index Seek,那究竟是为什么呢?

      我们知道,对於一条SQL语句,执行大概是这样: (1)语法分析 (2)编译并且产生执行计划 (3)执行
      对於同一句SQL, SQLServer可以产生无数个不同执行计划,究竟要选择哪一个执行计划呢,这个就是优化器(Optimizer)要干的事, 它会依据每一个操作符需要的成本来决定使用总成本最低的执行计划。
      先看一下上面SQL的执行成本,

      (1).清除Buffer  执行 DBCC DropCleanBuffers  DBCC FlushProcInDb(<db_id>)
      (2).执行 Set Statistics IO ON  Set Statistics Time ON
      (3).执行语句.
      以下是执行结果:

      SQL Server parse and compile time:
         CPU time = 16 ms, elapsed time = 500 ms.

      (影響 10750 個資料列)

      Table 'tblStockVar'. Scan count 1, logical reads 91690, physical reads 2, read-ahead reads 91835.

      SQL Server Execution Times:
         CPU time = 1109 ms,  elapsed time = 71024 ms.

      整个的执行时间是71.024秒

      如果我们手动加上IX_tblStockVar_VarDate的使用呢?
      SELECT WHCode , LocoID  , PartCode  , LotNo  , Sum ( VarStockQty  ) AS VarStockQty  , Sum ( VarBadQty  ) AS VarBadQty 
      FROM  tblStockVar  WITH(INDEX(IX_TblStockVar_VarDate))
      WHERE  VarDate   > 20060801
      GROUP BY WHCode , LocoID  , PartCode  , LotNo

      产生执行计划如下:
        |--Hash Match(Aggregate, HASH:([tblStockVar].[WHCode], [tblStockVar].[LocoID], [tblStockVar].[PartCode], [tblStockVar].[LotNo]), RESIDUAL:((([tblStockVar].[WHCode]=[tblStockVar].[WHCode] AND [tblStockVar].[LocoID]=[tblStockVar].[LocoID]) AND [tblStockVar
             |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([CustDB].[dbo].[tblStockVar]) WITH PREFETCH)
                  |--Index Seek(OBJECT:([CustDB].[dbo].[tblStockVar].[IX_tblStockVar_VarDate]), SEEK:([tblStockVar].[VarDate] > 20060801) ORDERED FORWARD)
      没错,跟我们预想的一样,先在VarDate索引上做Seek,然后再Bookmark Lookup.来看一下这段SQL的IO&Time.
      还是同样先Clear Buffer及Execute plan cache.然后再执行,以下是结果输出


      SQL Server parse and compile time:
         CPU time = 0 ms, elapsed time = 429 ms.

      (影響 10750 個資料列)

      Table 'tblStockVar'. Scan count 1, logical reads 416158, physical reads 443, read-ahead reads 236.

      SQL Server Execution Times:
         CPU time = 1438 ms,  elapsed time = 7840 ms.

      OMG!语句执行时间只有7.8秒!比上一条语句快了将近10倍!那究竟为什么SQL Server不选择使用IX_tblStock_Var的索引呢?欲知后事如何,且听下回分解。

       

       

      发表于 @ 2007年02月05日 10:59:00|评论(loading...)|编辑

       | 旧一篇: Welcome!

      评论

      #N_chow 发表于2007-02-05 12:30:53  IP: 219.130.91.*
      郁闷,文章内容怎么不出来呢??
      #ju_feng 发表于2008-05-15 17:28:12  IP: 218.241.130.*
      好文章啊,怎么没有继续呢?

      怎么也想不明白是用了Clustered Index Scan
      是VarDate 数据 20060801的数据比较多,
      记得None Clustered Index 选取度在5%下用

      但是为什么用了Clustered Index Scan?
      发表评论  


      当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
      Csdn Blog version 3.1a
      Copyright © N_chow