数据库引擎是高度优化的闭环系统,基于执行计划的反馈,查询优化器在一定程度上自动优化现有的执行计划。查询优化的核心是索引优化,数据库引擎通过计数器统计关于索引操作的数据,统计的信息包括:使用次数、物理存储、底层操作的计数,以及缺失索引等,这些统计数据存储在内存中,是数据库引擎执行情况的真实反馈,高度概括了索引的执行情况,有意识地利用索引的统计信息,有针对性地优化现有的业务逻辑代码,调整查询的执行计划,能够提高数据库的查询性能。
一,统计索引的使用次数
用户向SQL Server提交查询请求,在查询请求生成的执行计划中,每一个单独的索引操作(Seek、Scan、Lookup、或update)都会被存储到sys.dm_db_index_usage_stats 中,相应的计数器的值就会增加。例如,user_updates 计数器统计在索引上执行的Insert、Update或Delete操作的次数,查找计数器(user_seeks, user_scans, user_lookups)统计在索引上执行的seek、scan和lookup操作的次数,如果查找计数器远远小于user_updates 计数器,这说明基础表会执行大量的更新操作,维护索引更新的开销比较大,数据库引擎利用索引提升查询性能的空间有限。
在计数时,每一个单独的seek、scan、lookup或update操作都被计算为对该索引的一次使用,并使该视图中的相应计数器加1。
索引的Seek,Scan,Lookup和Update的含义是:
- Seek是Index Seek:通过该索引进行查找的次数
- Scan是Index Scan:通过该索引执行扫描查找的次数
- Lookup是Key Lookup:通过该索引查找到数据后,再到源数据表进行键值查找的次数,Key Lookup是非聚集索引特有的,查询性能低下,应避免这种查找方法;
- Update是Index Update:由于源表数据更新导致索引页更新的次数
Index Seek和Index Scan的区别是:
- Index Seek是从BTree的根节点开始,向子节点查找,直到叶子节点;
- Index Scan是在Index的叶子节点上,从左到右,把整个BTree的叶子节点遍历一遍,类似于Table Scan。
如果索引的Seek,Scan,Lookup的计数值较多,那么说明索引被引用的次数多;如果查找计数器数值较小,但是Update数值较多,说明维护Index的开销高于查询带来的性能提升,应该考虑修改索引的结构,或者直接把索引删除。
select db_name(us.database_id) as db_name ,object_schema_name(us.object_id)+'.'+object_name(us.object_id) as table_name ,i.name as index_name ,i.type_desc as index_type_desc ,us.user_seeks ,us.user_scans ,us.user_lookups ,us.user_updates from sys.dm_db_index_usage_stats us inner join sys.indexes i on us.object_id=i.object_id and us.index_id=i.index_id where us.database_id=db_id() --us.database_id=db_id('database_name') --and us.object_id=object_id('schema_name.table_name') order by us.user_seeks desc