隨着SQL Server 2005版本的發佈,帶來了一種新的用於訪問系統和數據庫信息的方式,而無需創建複雜的查詢或直接訪問系統表。通過使用SQL Server動態管理視圖(DMVs),你可以查看SQL Server的實例信息,比如實例運行在什麼系統上、實例中有那些數據庫。
你可以在Transact-SQL語句中引用你想要查看的視圖名稱來調用DMVs。所有的DMVs都存放在SYS架構中,這個預定義架構包含了系統視圖。它們以字符dm_開頭,如sys.dm_os_hosts。
與其他類型的視圖一樣,SQL Server DMVs返回一個指定數據類型的列集合。但是,一個DMV的架構會隨着SQL Server版本的變化而變化。因此,當編寫調用DMV的代碼時,你應該指定列名而不是使用類似SELECT * FROM view_name之類的語法。
SQL Server動態管理視圖可分爲兩大類:一類是描述數據庫級別的信息,另一類是描述服務器級別的信息。在本文中,我將演示如何使用前者,後者我將會在以後的文章中加以闡述。本文例子所使用的系統環境是一個創建在本地的SQL Server 2008實例。例子中引用的數據庫是AdventureWorks 2008示例數據庫,除了一個例子使用了SQL Server Reporting Services數據庫。對於每一個例子,我都會列出語句運行的結果集。很可能你的結果集會有所不同,這取決於你在哪種系統上運行SQL Server以及如何修改數據庫的。
與數據庫相關的SQL Server DMVs
我們查看的第一個SQL Server DMV是sys.dm_db_partition_stats,它返回當前數據庫中的分區信息,每個分區一行。(如果一個索引、一個堆或者一個沒有索引的表未被分區,它被認爲是一個分區。)該視圖返回的信息包括分區使用的頁面數量和總行數。在下面的SELECT語句中,我使用這個DMV來獲取AdventureWorks 2008數據庫中Production.Product表的分區信息:
USE AdventureWorks2008; GO SELECT index_id AS IndexID, partition_number AS PartitionNum, used_page_count AS UsedPageCount, row_count AS TotalRows FROM sys.dm_db_partition_stats WHERE object_id = OBJECT_ID('Production.Product') ORDER BY IndexID, PartitionNum; |
如語句所示,sys.dm_db_partition_stats動態管理視圖返回的信息首先是索引或堆的識別號然後是分區號。換句話說,定義的分區號與特定的索引或堆相關,所以每個索引或堆可以有一個或多個分區。(這個分區號不同於數據庫分配給每個分區的獨一無二的分區ID。)
緊接着索引ID和分區號,還將返回該分區的頁面總數和使用的總行數,結果如下表所示:
IndexID |
ParitionNum |
UsedPageCount |
TotalRows |
1 |
1 |
15 |
504 |
2 |
1 |
4 |
504 |
3 |
1 |
5 |
504 |
4 |
1 |
4 |
504 |
如上表所示,在PRODUCT表中每個索引或堆都只有一個分區,每個分區有504行。
接下來的動態管理視圖,我會介紹sys.dm_sql_referenced_entities。該視圖返回指定對象所引用的用戶定義的數據庫對象集合,每個對象一行。例如,如果一個存儲過程引用了用戶定義的表,則動態管理視圖將爲每個表返回一行。
實際上,sys.dm_sql_referenced_entities並不是一個視圖,它是一個函數。在下面的SELECT語句中,我使用sys.dm_sql_referenced_entities函數來檢索觸發器iuPerson所引用的對象列表,如下所示:
USE AdventureWorks2008; GO SELECT referenced_schema_name AS SchemaName, referenced_entity_name AS EntityName, referenced_class_desc AS ClassName FROM sys.dm_sql_referenced_entities ('Person.iuPerson', 'OBJECT') ORDER BY SchemaName, EntityName; |
觸發器iuPerson是Person架構的一部分,與Person表相關。當我調用該函數時,需要指定觸發器名稱和OBJECT參數選項。如果它是一個數據庫級觸發器,則需要指定DATABASE_DDL_TRIGGER參數選項。如果它是一個服務器級觸發器,則需要指定SERVER_DDL_TRIGGER參數選項。下表顯示SELECT語句返回的信息:
SchemaName |
EntityName |
ClassName |
NULL |
Person |
OBJECT_OR_COLUMN |
NULL |
Person |
OBJECT_OR_COLUMN |
Demographics |
exist |
OBJECT_OR_COLUMN |
Person |
Person |
OBJECT_OR_COLUMN |
Person |
Person |
OBJECT_OR_COLUMN |
Person |
Person |
OBJECT_OR_COLUMN |
請注意,返回的是AdventureWorks 2008數據庫中iuPerson觸發器所引用對象的架構名稱、實體名稱和類別。
另一個你可能會發現有用的數據庫管理函數是sys.dm_sql_referencing_entities,它返回數據庫中的某個實體引用另一個用戶定義實體的信息,每個實體一行。例如,在下面的語句中使用該函數來檢索Production.ProductInventory表所引用對象的架構、實體及類別:
USE AdventureWorks2008; GO SELECT referencing_schema_name AS SchemaName, referencing_entity_name AS EntityName, referencing_class_desc AS ClassName FROM sys.dm_sql_referencing_entities ('Production.ProductInventory', 'OBJECT') ORDER BY SchemaName, EntityName; |
與前面的例子中,我提供的參考對象是ProductInventory表,並使用了OBJECT參數選項。下面的結果表明,該表引用了四個用戶定義的對象:
SchemaName |
EntityName |
ClassName |
dbo |
fn_inventory |
OBJECT_OR_COLUMN |
dbo |
ufnGetStock |
OBJECT_OR_COLUMN |
Production |
CK_ProductInventory_Bin |
OBJECT_OR_COLUMN |
Production |
CK_ProductInventory_Shelf |
OBJECT_OR_COLUMN |
還有一個動態管理函數是sys.dm_db_index_physical_stats,它返回指定表或視圖的索引和數據的大小和碎片信息。在下面的SELECT語句中,我將數據庫名稱和表名稱作爲函數的前兩個參數:
USE AdventureWorks2008; GO SELECT index_id AS IndexID, index_type_desc AS IndexType, fragment_count AS FragCount, page_count AS TotalPages FROM sys.dm_db_index_physical_stats (DB_ID('AdventureWorks2008'), OBJECT_ID('Person.Person'), NULL, NULL, NULL) ORDER BY IndexID; |
正如你所看到的,sys.dm_db_index_physical_stats還需要三個額外的參數,在例子中已經被指定爲NULL值。這三個參數分別代表:索引ID、分區號和用於獲取統計信息的掃描模式。因爲我想了解表上所有索引和分區的信息,我爲前兩個參數指定了NULL值。關於模式,NULL值表示將使用有限的掃描模式,而不是詳盡或採樣掃描模式。SELECT語句返回以下結果:
IndexID |
IndexType |
FragCount |
TotalPages |
1 |
CLUSTERED INDEX |
5 |
3807 |
2 |
NONCLUSTERED INDEX |
2 |
103 |
3 |
NONCLUSTERED INDEX |
2 |
57 |
256000 |
PRIMARY XML INDEX |
1 |
3 |
256001 |
PRIMARY XML INDEX |
7 |
2152 |
256002 |
XML INDEX |
33 |
1386 |
256003 |
XML INDEX |
33 |
1385 |
256004 |
XML INDEX |
35 |
1386 |
返回結果包括與Person表相關的索引ID、索引類型、碎片數量和頁數。
現在,讓我們回到SQL Server動態管理視圖。動態管理視圖sys.dm_db_index_usage_stats返回自上一次啓動SQL Server服務啓動以來不同的索引操作類型的統計信息,如檢索和掃描。在下面的SELECT語句中,我查看本地SQL Server實例中最近的索引操作使用的統計信息。
USE AdventureWorks2008; GO SELECT OBJECT_NAME(object_id) AS ObjectName, index_id AS IndexID, user_seeks AS UserSeeks,< user_scans AS UserScans FROM sys.dm_db_index_usage_stats WHERE database_id = DB_ID('AdventureWorks2008') ORDER BY ObjectName, IndexID; |
注意,對於每個操作可查詢到對象的名稱、該對象對應的索引ID以及用戶檢索和掃描的次數。下面的結果表明,自SQL Server服務實例啓動以來只有較少數量的檢索和掃描:
ObjectName |
IndexID |
UserSeeks |
UserScans |
Document |
1 |
1 |
0 |
JobCandidate |
1 |
1 |
0 |
ProductReview |
1 |
1 |
0 |
SalesOrderHeader |
1 |
0 |
1 |