遇到了这样的一个例子:SQL Server索引统计信息未及时更新,导致排序混乱 我们知道,在sql server上创建索引后,同时会对该索引上的值进行排序,但对于新增加的值,如果未能及时更新统计信息,将有可能导致排序的混乱,也就是没有排序。 这是产生问题的语句:Select * From V_L_IcStockProInEntry Where FInterID= '329482' V_L_IcStockProInEntry是一个视图,其语句如下:SELECT t2.FInterID, t2.FSeq, t2.FItemID, t2.FMustQty, t2.FQty   
FROM dbo.IcStockProIn AS t1 INNER JOIN    
dbo. IcStockProInEntry AS t2 ON t1.FInterID = t2.FInterID LEFT OUTER JOIN    
dbo.t_IcItem AS t3 ON t2.FItemID = t3.FItemID LEFT OUTER JOIN    
dbo.IcProductTrace AS d ON t2.FTraceInterid = d.FInterID LEFT OUTER JOIN    
dbo.t_IcItemPrimary AS e ON d.FMainItemID = e.FItemID LEFT OUTER JOIN    
dbo.t_EventType AS t10 ON t2.FQulityID = t10.FID LEFT OUTER JOIN    
dbo.t_Customer AS h ON t2.FCustID = h.FID LEFT OUTER JOIN    
dbo.V_WorkItem AS i ON t2.FStWorkItemID = i.FitemID LEFT OUTER JOIN    
dbo.IcShopMo AS G ON G.FinterID = t2.FSourceInterID    查询的结果是finterid对应的多个fseq值未能正常排序。finterid和fseq 属于icstockproinentry表的列,在这两列上有个聚集索引,所以会自动的排序。但由于数据更新较快,新插入的值未能及时有效排序,所以导致了排序的混乱。首先来看下柱状图:dbcc show_statistics('IcStockProInEntry',PK_IcStockProInEntry)RANGE_HI_KEY    RANGE_ROWS    EQ_ROWS    DISTINCT_RANGE_ROWS    AVG_RANGE_ROWS
3    0    1    0    1...
....
282987    101155    6    27942    3.620178
288803    18440    1    5253    3.510375
296886    24587    6    7468    3.292314
303529    18433    19    5799    3.178652
329478    71674    6    23077    3.105863
329480    0    4    0    1可以看到,当前的RANGE_HI_KEY 的值未329480,而查询语句中的finterid值未329482,并未纳入统计。而查询329480前的值,其排序是正常的。如果更新下聚集索引的统计信息,就可以发现又正常了。更新某个索引的统计信息可用
UPDATE STATISTICS
更新完索引的统计信息后,排序就正常了。这是我的一个发现,但不知道是否正确,不知谁也碰过这种情况呢?

解决方案 »

  1.   

    1) 排序问题要ORDER BY解决。2) 统计信息可以设定自动更新(AUTO_UPDATE_STATISTICS 设为ON).3) 排程每周一次的Rebuild Index很重要(具体排期依你的负载来定)
      

  2.   

    由于聚集索引已经排序,所以就算有ORDER BY 也不会影响效能,就放心大胆的加ORDER BY 吧,哈哈
      

  3.   

    索引的统计信息是执行计划依赖的一个重要因素
    对于插入量很大的表来讲,统计信息是经常根不上的,如果查询最新的数据,往往会是index scan而不是index seek,常用的办法是强制索引。对于需要排序的sql,显示指定order by 才是最稳妥的方法。