zoukankan      html  css  js  c++  java
  • SQL Server 优化合理使用聚集索引

          今天在监控数据库时,发现一个语句的执行时间比较长,IO次数也比较多。语句如下:

    select * from Docbase this_ where 
     id 
    in ( select objid from Categorylink categorylink where 
    categorylink.objtype
    ='Docbase' and (categorylink.categoryid = 
    '4028827015a82d020115d07b6b604689')) and pid is null and isdelete=0 and
    exists(select 'X' from Permissiondetail p where p.objid=this_.id and 
    p.objtable
    ='docbase'and  p.userid in('','ISALLUSER','402882ed0eb78aae010ec124f7fe5c87',
    '402881a10d33db44010d3402fc2b00c3'and 10 between p.minseclevel and p.maxseclevel and p.opttype > 2 ) and not exists (select 'X' from Delobj del where del.objid=this_.id and del.objtable='Docbase'

       由于表Permissiondetail表数据有很多,大约有几百万条数据,先前建立一个索引来达到索引覆盖,避免表扫描。

    CREATE  INDEX [IX_PERMISSIONDETAIL_mu] ON [dbo].[permissiondetail] 
    (
        
    [objid] ASC,[objtable]ASC,[userid] ASC,[minseclevel] ASC,[maxseclevel] ASC,[opttype] ASC
    )

       执行结果如下:

    (495 行受影响)
    表 
    'delobj'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'docbase'。扫描计数 1,逻辑读取 659 次,物理读取 0 次,预读 0 次,lob 逻辑读取 85 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'categorylink'。扫描计数 3,逻辑读取 36 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'Permissiondetailworkflowbase'。扫描计数 1,逻辑读取 30690 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

      后来发现这样的优化效果也是不明细,因为这里运行的速度也不是很快,因为数据库是Index scan,他会对索引的全部数据进行扫描。一旦数据量大,也很慢,而且这个索引的长度太长了,影响DML语句。后来通过分析表的数据分布。和userid的数据情况,在userid里建立一个聚集索引,效率会大于索引覆盖。

    CREATE clustered INDEX [IX_PERMISSIONDETAIL_userid] ON [dbo].[permissiondetail] ( [userid] ASC)

       执行语句结果:

    (495 行受影响)
    表 
    'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'Permissiondetail'。扫描计数 1988,逻辑读取 10106 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'docbase'。扫描计数 1,逻辑读取 659 次,物理读取 0 次,预读 0 次,lob 逻辑读取 87 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'categorylink'。扫描计数 1,逻辑读取 12 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    表 
    'delobj'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

        结果:是IO次数比先前提高了3倍,而且DML的影响是比较少的。

      总结:

        这个案例有个特殊性,就是对Permissiondetail大表会有查询很多的数据,这时如果不能达到索引覆盖,执行的时间比较长,但是这样的做饭牺牲了很多其他的性能:插入,更新和删除数据,不是最优的。我们更改了索引,将userid改成聚集索引,一样达到了提高效率的方法,同时也提高了DML的效率。

       有时:聚集索引效率>索引覆盖,具体要看情况,这只是其中的一个例子。

  • 相关阅读:
    SQL语句中----删除表数据drop、truncate和delete的用法
    input绑定ng-model报错
    angular中使用promise
    js增删改除
    jQuery入门简记(增删改搜)
    ajax封装与兼容
    MySQL遇到check the manual that corresponds to your MySQL server version for the right syntax错误
    深入理解Java中的final关键字
    ubuntu设置samba
    设计模式之单例模式
  • 原文地址:https://www.cnblogs.com/zping/p/1303813.html
Copyright © 2011-2022 走看看