当前位置:首页 > 问答 > 正文

SQL Server里那些评价索引到底有没有用,怎么判断才靠谱一点

评价一个索引到底有没有用,不能光看它存不存在,或者凭感觉说“这个字段经常查,所以建个索引肯定快”,在SQL Server里,我们需要一些更实在、更客观的方法来判断,核心思路就两点:第一,看这个索引有没有被查询真正用上;第二,看用它带来的查询性能提升,是否值得它所占用的存储空间和维护成本(比如增删改数据时更新索引的开销)。

最直接也最可靠的方法,就是去检查SQL Server的执行计划,执行计划就像是SQL Server引擎亲自告诉你“我打算怎么执行你这条查询语句”的路线图,当你在SQL Server Management Studio (SSMS) 里运行一条查询时,可以在执行查询前,点击工具栏上的“显示估计的执行计划”按钮(那个带蓝箭头的图标),或者直接点击“包括实际执行计划”,两者的区别在于,前者是SQL Server根据统计信息预估的,后者是真正执行完查询后给出的实际路径,对于判断索引是否被使用,两者通常结果一致,但实际执行计划更精确。

在看执行计划时,你重点关注那些代表从表或索引中获取数据的操作符,最常见的是以下几种:

  1. 索引查找 (Index Seek):这是最理想的情况,它意味着查询条件能够精确定位到索引中的一小部分数据,好比在字典里按拼音字母顺序直接翻到某个字所在的页数,效率非常高,如果你在执行计划里看到这个操作符用到了你创建的索引,那说明这个索引设计得非常有效,它确实被用上了,而且用得很好。

  2. 索引扫描 (Index Scan):这种情况有点微妙,它意味着SQL Server遍历了整个索引来寻找需要的数据,就像你为了找一个字,把字典从头到尾翻了一遍,虽然它比全表扫描(下面会讲)可能稍快一点(因为索引通常比整个表的数据量小),但这通常意味着索引的设计可能不是最优的,你的查询需要返回的列,在索引中并不完全包含,导致SQL Server即使通过索引找到了行位置,还得回头去主表里把其他数据取出来(这会产生一个叫“键查找”的操作,通常是性能瓶颈),如果执行计划里总是出现针对某个索引的“索引扫描”,你就需要想想,这个索引的字段顺序是否合理,或者是否应该把查询中需要用到的列包含进来(创建包含列索引)。

    SQL Server里那些评价索引到底有没有用,怎么判断才靠谱一点

  3. 聚集索引扫描 (Clustered Index Scan)表扫描 (Table Scan):这基本是最糟糕的情况了,它意味着SQL Server决定完全忽略你创建的非聚集索引,直接读取整个表,这通常发生在两种情况下:一是你的查询条件根本无法利用索引(比如在索引字段上使用了函数计算);二是SQL Server经过成本计算,发现表里的数据量本来就不大,或者满足条件的数据非常多,用索引反而更慢(因为要频繁地在索引和主数据之间跳转),还不如直接全表扫描来得痛快,如果你期望使用索引的查询却出现了全表扫描,那这个索引在当前查询下可能就是“没用”的。

除了看单次查询的执行计划,SQL Server还提供了两个非常强大的动态管理视图(DMV)来帮你从宏观层面评估索引的使用情况,这是DBA常用的“法宝”,根据微软官方文档和大量DBA的实践经验,这两个DMV是sys.dm_db_index_usage_statssys.dm_db_index_operational_stats

  • sys.dm_db_index_usage_stats:这个视图记录了自SQL Server上次重启以来,各个索引被用于用户查询的情况,你需要重点关注几个列:

    SQL Server里那些评价索引到底有没有用,怎么判断才靠谱一点

    • user_seeks:索引被用于查找的次数。
    • user_scans:索引被用于扫描的次数。
    • user_lookups:通过索引进行键查找的次数(通常与书签查找相关)。
    • user_updates:由于表中数据增删改而导致索引需要更新的次数。

    如果一个索引的user_seeksuser_scansuser_lookups这几项值都非常低(比如接近0),但user_updates却很高,那就这是一个强烈的信号,表明这个索引几乎没帮上什么查询的忙,反而一直在拖慢你的数据写入操作,这种索引就是典型的“负资产”,是需要考虑删除的候选对象。

  • sys.dm_db_index_operational_stats:这个视图提供了更底层的I/O、锁定、闩锁等统计信息,它可以帮你发现那些虽然被使用,但可能因为设计不当而导致底层资源争用严重的索引,某个索引的页闩锁等待时间非常长,可能意味着它成为了并发瓶颈。

SQL Server自带的“缺失索引”功能也能提供线索,当你执行查询时,如果查询优化器认为“如果存在某个索引,我这个查询会快很多”,它就会把这条建议记录下来,你可以在sys.dm_db_missing_index_details等DMV中查到这些建议。对这个功能一定要谨慎对待,它给出的建议往往是“头痛医头”,只针对当前单个查询,可能建议你创建的索引字段会与其他已有索引重复,或者导致索引过多,你需要综合评估后再决定是否采纳。

靠谱的判断流程是:针对关键或缓慢的查询,查看其执行计划,确认你关心的索引是被“查找”了还是被“扫描”了,或者根本没用上,定期(比如每周或每月)查询索引使用情况的DMV,找出那些长期闲置、只有维护成本没有查询收益的索引,结合“缺失索引”建议,通盘考虑整个数据库的索引结构,进行优化或清理,没有一劳永逸的索引策略,随着数据量和查询模式的变化,定期审查索引的有效性是一项必须进行的工作。