[原] JT SQL Server 性能调优札记之三

提出方案

以下是找出来的TOP SQL 。

select distinct s.parentId,s.pkId,1,s.title,s.comeOrg,s.fileDate,
    s.fileName,s.filePath,1,l.optionstatus,s.remark3,urgencyLevel
    from shouwen as s, 
    jt_ComitOA.dbo.log as l 
    where 
    (s.fileSerialNumber like '%%' or s.title like '%%' 
     or s.keywords like '%%' or s.fileZi like '%%') 
     and  s.status<>'4' 
     and s.pkid in
        (select distinct(mid) from log where uid='glzyf' and typeid='shouwen')
     and l.mid=s.pkid and uid='glzyf' and typeid='shouwen'
order by s.fileDate desc  

从执行计划中可以看到两个比较大操作,两个对Log表“聚集索引扫描”,观察语句不难以下发现就是导致两个“聚集索引扫描”的原因。

(select distinct(mid) from log where uid='glzyf' and typeid='shouwen')
and l.mid=s.pkid and uid='glzyf' and typeid='shouwen'

这次运气比较好,mid、uid和typeid都在这两个语句里面,于是我计划在Log表的mid、uid和typeid上面建索引

CREATE NONCLUSTERED INDEX [idx_log__uid_typeid] ON [Log] 
(
    [uid] ASC,
    [typeID] ASC,
    [mid] ASC
);
看一下执行计划新的执行计划:

建索引后的执行计划2

留意左上角对ShouWen这个表的聚集索引扫描,由原先的相对比例0%(其实是接近0%),上升到27%,可见整体的资源消耗已经大大降低了。

表 'Log'。扫描计数 2,逻辑读取 3272 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'ShouWen'。扫描计数 1,逻辑读取 1436 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 62 毫秒,占用时间 = 293 毫秒。

对Log表的访问量大大减少,这可是有25万条数据的表啊,总的执行时间更是大大减少,疗效相当的不错啊。

至此,可以认为该调优已经达到很好的效果了,从26秒的执行时间缩减到0.3秒,非常不错的成绩了。

 

审视方案

在新的执行计划中有两个键查找,键查找用来检索筛选索引没有涵盖的剩余列,说白了,就有一些输出列不在这个索引的覆盖范围中。看一下select的输出,的确有一个Log表的optionstatus字段,于是将索引的创建语句调整为:

CREATE NONCLUSTERED INDEX [idx_log__uid_typeid] ON [Log] 
(
    [uid] ASC,
    [typeID] ASC,
    [mid] ASC
)
INCLUDE ( [optionstatus])

image 

同样以左上角的ShouWen表的“聚集索引扫描”为参照点,就执行计划来看,的确资源占用率再次大大降低了,看看执行的统计信息。

表 'Log'。扫描计数 2,逻辑读取 16 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'ShouWen'。扫描计数 1,逻辑读取 1436 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 78 毫秒,占用时间 = 282 毫秒。

Log表的逻辑读取数大大减少,执行时间并没有太大变化。这是由于这次缩减的是逻辑读,即在缓存中读取,通常缓存是在内存中的,内存可是比磁盘快多了。

posted @ 2009-02-20 10:06 killkill 阅读(2742) 评论(10) 编辑 收藏

 回复 引用 查看   
#1楼[楼主] 2009-02-20 10:08 killkill      
终于将第三篇发出来了
抢个板凳
连着看的,还不错!

 回复 引用   
#3楼 2009-02-20 11:03 no_name[未注册用户]
写得不错
说白了,就是索引覆盖

 回复 引用 查看   
#4楼[楼主] 2009-02-20 11:13 killkill      
@no_name
请留意下一篇——真凶,非常的意想不到。

 回复 引用 查看   
#5楼 2009-02-20 11:20 编程入门      
索引没怎么用,关键现在用的都是小数据,好文章
 回复 引用   
#6楼 2009-02-20 11:32 linglongju[未注册用户]
LZ啊,create index 的 include是什么意思啊。
 回复 引用   
#7楼 2009-02-20 11:40 I love AWP[未注册用户]
很喜欢LZ的SQL Server 文章
 回复 引用 查看   
#8楼 2009-02-20 13:22 Keep Walking      
@linglongju
sql2005新增的包含性列

 回复 引用 查看   
#9楼 2009-02-20 13:23 Keep Walking      
你现在给log类型表建了这么多索引是快意了,等到你的log表并发插入的时候你就知道你的性能有非常大的降低了
 回复 引用 查看   
#10楼[楼主] 2009-02-20 13:54 killkill      
@Keep Walking
这里的确是没有说清楚,Log表名貌似是用来存放Log,但是据我我观察其实一个连接表,插入操作肯定是有的,但是不会太频繁。
SQL Profiler显示建的索引是:
CREATE NONCLUSTERED INDEX [idx_log__uid_typeid] ON [Log]
(
[uid] ASC,
[typeID] ASC,
[mid] ASC,
[optionstatus]
)
我也是怕索引太大,所以调整为这样建索引。