以下查询正确输出查找、扫描等次数。我对理解输出中的某些行有疑问。在查询的某些输出行中,索引名称显示为NULL
,index_type
显示为HEAP
,并NumOfSeeks
显示为 0;NumOfScans
而在同一行中,它为和/或显示了一些非零数字NumOfLookups
。问题:我们如何解释这些行?
备注:所有表都没有聚簇索引,因此所有表都是 HEAP。但是在以下查询的输出的大多数行中,显示的是索引名称(而不是显示为 NULL),并且还显示了 index_type(显示为 NONSLUSTER)。因此,问题特定于此评论上面描述的输出行。
参考:sys.dm_db_index_usage_stats。
SELECT OBJECT_NAME(IX.OBJECT_ID) Table_Name
,IX.name AS Index_Name
,IX.type_desc Index_Type
,SUM(PS.[used_page_count]) * 8 IndexSizeKB
,IXUS.user_seeks AS NumOfSeeks
,IXUS.user_scans AS NumOfScans
,IXUS.user_lookups AS NumOfLookups
,IXUS.user_updates AS NumOfUpdates
,IXUS.last_user_seek AS LastSeek
,IXUS.last_user_scan AS LastScan
,IXUS.last_user_lookup AS LastLookup
,IXUS.last_user_update AS LastUpdate
FROM sys.indexes IX
INNER JOIN sys.dm_db_index_usage_stats IXUS ON IXUS.index_id = IX.index_id AND IXUS.OBJECT_ID = IX.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats PS on PS.object_id=IX.object_id
WHERE OBJECTPROPERTY(IX.OBJECT_ID,'IsUserTable') = 1
GROUP BY OBJECT_NAME(IX.OBJECT_ID) ,IX.name ,IX.type_desc ,IXUS.user_seeks ,IXUS.user_scans ,IXUS.user_lookups,IXUS.user_updates ,IXUS.last_user_seek ,IXUS.last_user_scan ,IXUS.last_user_lookup ,IXUS.last_user_update
堆是 SQL Server 中基表的名称,当它上面没有聚集索引时。您可以自由地在堆上创建非聚集索引。
堆没有名称,
sys.indexes
因为它们不是索引。堆最常见的描述方式是无序页面。索引是按索引键中的列逻辑排序的页面。您可以重新加入
sys.tables
并用于ISNULL
将索引名称替换为堆的基表名称。虽然在某些边缘情况下您可以在没有索引的情况下进行搜索,但行是通过内部标识符在堆中标识的,该标识符不容易暴露给用户,或者在正常编写的查询中用作可搜索谓词。
正如您已经注意到的那样,如果没有聚集索引,表本身将存储在堆数据结构中。这些行来自
sys.dm_db_index_usage_stats
表示有关堆在查询计划中使用了多少次、是否被完全扫描等的指标。根据定义,堆是一组无序的数据,因此无法像聚集索引那样有效地对其进行查找。这就是为什么查找次数为 0 但扫描次数可以大于 0(这再次有效地意味着扫描了整个堆)。如果您的表上有聚集索引,那么数据将存储在 B 树中,而不是堆中。然后您会看到该聚集索引(及其名称)的行而不是堆的行。
对于大多数一次不涉及大部分数据的查询来说,无法被搜索通常是堆的性能低于聚集索引表的原因。