標籤:SQL SERVER/MSSQL SERVER/數據庫/DBA/索引/統計信息數據庫
不管什麼時候對基礎數據執行插入、更新或刪除操做,SQL Server 數據庫引擎都會自動維護索引。隨着時間的推移,這些修改可能會致使索引中的信息分散在數據庫中(含有碎片)。當索引包含的頁中的邏輯排序(基於鍵值)與數據文件中的物理排序不匹配時,就存在碎片。碎片很是多的索引可能會下降查詢性能,致使應用程序響應緩慢,因此在平常的維護工做當中就須要對索引進行檢查對那些填充度很低碎片量大的索引進行從新生成或從新組織,可是在這個過程也須要注意一些小的細節,不然會產生錯誤。express
1、語法架構
語法內容載自SQL Server聯機叢書,標記出了須要注意的內容,最後分享本身平時用的維護索引的語句供參考。併發
ALTER INDEX { index_name | ALL } ON <object> { REBUILD [ [PARTITION = ALL] [ WITH ( <rebuild_index_option> [ ,...n ] ) ] | [ PARTITION = partition_number [ WITH ( <single_partition_rebuild_index_option> [ ,...n ] ) ] ] ] | DISABLE | REORGANIZE [ PARTITION = partition_number ] [ WITH ( LOB_COMPACTION = { ON | OFF } ) ] | SET ( <set_index_option> [ ,...n ] ) } [ ; ] <object> ::= { [ database_name. [ schema_name ] . | schema_name. ] table_or_view_name } <rebuild_index_option > ::= { PAD_INDEX = { ON | OFF } | FILLFACTOR = fillfactor | SORT_IN_TEMPDB = { ON | OFF } | IGNORE_DUP_KEY = { ON | OFF } | STATISTICS_NORECOMPUTE = { ON | OFF } | ONLINE = { ON | OFF } | ALLOW_ROW_LOCKS = { ON | OFF } | ALLOW_PAGE_LOCKS = { ON | OFF } | MAXDOP = max_degree_of_parallelism | DATA_COMPRESSION = { NONE | ROW | PAGE } [ ON PARTITIONS ( { <partition_number_expression> | <range> } [ , ...n ] ) ] } <range> ::= <partition_number_expression> TO <partition_number_expression> } <single_partition_rebuild_index_option> ::= { SORT_IN_TEMPDB = { ON | OFF } | MAXDOP = max_degree_of_parallelism | DATA_COMPRESSION = { NONE | ROW | PAGE } } } <set_index_option>::= { ALLOW_ROW_LOCKS = { ON | OFF } | ALLOW_PAGE_LOCKS = { ON | OFF } | IGNORE_DUP_KEY = { ON | OFF } | STATISTICS_NORECOMPUTE = { ON | OFF } }
索引的名稱。索引名稱在表或視圖中必須惟一,但在數據庫中沒必要惟一。索引名稱必須符合標識符的規則。函數
指定與表或視圖相關聯的全部索引,而不考慮是什麼索引類型。若是有一個或多個索引脫機或不容許對一個或多個索引類型執行只讀文件組操做或指定操做,則指定 ALL 將致使語句失敗。下表列出了索引操做和不容許使用的索引類型。性能
已分區表和已分區索引。
數據庫的名稱。優化
表或視圖所屬架構的名稱。ui
與該索引關聯的表或視圖的名稱。若要顯示對象的索引報表,請使用 sys.indexes 目錄視圖。lua
指定將使用相同的列、索引類型、惟一性屬性和排序順序從新生成索引。此子句等同於 DBCC DBREINDEX。REBUILD 啓用已禁用的索引。從新生成彙集索引並不從新生成關聯的非彙集索引,除非指定了關鍵字 ALL。若是未指定索引選項,則應用存儲在 sys.indexes 中的現有索引選項值。對於未在 sys.indexes 中存儲值的任何索引選項,應用該選項的參數定義中指示的默認值。spa
從新生成 XML 索引或空間索引時,選項 ONLINE = ON 和 IGNORE_DUP_KEY = ON 無效。
若是指定 ALL 且基礎表爲堆,則從新生成操做對錶沒有任何影響。從新生成與表相關聯的全部非彙集索引。
若是數據庫恢復模式設置爲大容量日誌記錄或簡單,則能夠對從新生成操做進行最小日誌記錄。
指定只從新生成或從新組織索引的一個分區。若是 index_name 不是已分區索引,則不能指定 PARTITION。
PARTITION = ALL 從新生成全部分區。當指定PARTITION = ALL時不能使用ONLINE = ON
要從新生成或從新組織已分區索引的分區數。partition_number 是能夠引用變量的常量表達式。其中包括用戶定義類型變量或函數以及用戶定義函數,但不能引用 Transact-SQL 語句。partition_number 必須存在,不然,該語句將失敗。
SORT_IN_TEMPDB、MAXDOP 和 DATA_COMPRESSION 是在從新生成單個分區 (PARTITION = n) 時能夠指定的選項。不能在單個分區從新生成操做中指定 XML 索引。
不能聯機從新生成分區索引。在此操做過程當中將鎖定整個表。
將索引標記爲已禁用,從而不能由 數據庫引擎使用。任何索引都可被禁用。已禁用的索引的索引定義保留在沒有基礎索引數據的系統目錄中。禁用匯集索引將阻止用戶訪問基礎表數據。若要啓用索引,請使用 ALTER INDEX REBUILD 或 CREATE INDEX WITH DROP_EXISTING。
指定將從新組織的索引葉級。此子句等同於 DBCC INDEXDEFRAG。ALTER INDEX REORGANIZE 語句始終聯機執行。這意味着不保留長期阻塞的表鎖,且對基礎表的查詢或更新能夠在 ALTER INDEX REORGANIZE 事務處理期間繼續。不能爲已禁用的索引或 ALLOW_PAGE_LOCKS 設置爲 OFF 的索引指定 REORGANIZE。
指定壓縮全部包含大型對象 (LOB) 數據的頁。LOB 數據類型包括 image、text、ntext、varchar(max)、nvarchar(max)、varbinary(max) 和 xml。壓縮此數據能夠改善磁盤空間使用狀況。默認值爲 ON。
壓縮全部包含大型對象數據的頁。
從新組織指定的彙集索引將壓縮彙集索引中包含的全部 LOB 列。從新組織非彙集索引將壓縮做爲索引中非鍵(已包括)列的全部 LOB 列。有關詳細信息,請參閱建立帶有包含列的索引。
指定 ALL 時,將從新組織與指定表或視圖相關聯的全部索引,而且壓縮與彙集索引、基礎表或具備包含列的非彙集索引相關聯的全部 LOB 列。
不壓縮包含大型對象數據的頁。
OFF 對堆沒有影響。
若是 LOB 列不存在,則忽略 LOB_COMPACTION 子句。
指定不從新生成或從新組織索引的索引選項。不能爲已禁用的索引指定 SET。
指定索引填充。默認值爲 OFF。
FILLFACTOR 指定的可用空間百分比應用於索引的中間級頁。若是在 PAD_INDEX 設置爲 ON 的同時不指定 FILLFACTOR,則使用 sys.indexes 中存儲的填充因子值。
中間級頁已填充到接近容量限制。這樣將至少爲索引能夠基於中間頁中的鍵集擁有的最大大小的一行留出足夠的空間。
指定一個百分比,指示在建立或更改索引期間,數據庫引擎對各索引頁的葉級填充的程度。fillfactor 必須爲介於 1 至 100 之間的整數值。默認值爲 0。
填充因子的值 0 和 100 在全部方面都是相同的。
顯式的 FILLFACTOR 設置只是在索引首次建立或從新生成時應用。數據庫引擎並不會在頁中動態保持指定的可用空間百分比。有關詳細信息,請參閱 CREATE INDEX (Transact-SQL)。
若要查看填充因子設置,請使用 sys.indexes。
使用 FILLFACTOR 值建立或更改彙集索引會影響數據佔用的存儲空間量,由於數據庫引擎在建立彙集索引時會再分發數據。
指定是否在 tempdb 中存儲排序結果。默認值爲 OFF。
在 tempdb 中存儲用於生成索引的中間排序結果。若是 tempdb 位於不一樣於用戶數據庫的磁盤集中,這樣可能會縮短建立索引所需的時間。可是,這會增長索引生成期間所使用的磁盤空間量。
中間排序結果與索引存儲在同一數據庫中。
若是不須要執行排序操做,或者能夠在內存中進行排序,則忽略 SORT_IN_TEMPDB 選項。
指定在插入操做嘗試向惟一索引插入重複鍵值時的錯誤響應。IGNORE_DUP_KEY 選項僅適用於建立或從新生成索引後發生的插入操做。當執行 CREATE INDEX、ALTER INDEX 或 UPDATE 時,該選項無效。默認值爲 OFF。
向惟一索引插入重複鍵值時將出現警告消息。只有違反惟一性約束的行纔會失敗。
向惟一索引插入重複鍵值時將出現錯誤消息。整個 INSERT 操做將被回滾。
對於對視圖建立的索引、非惟一索引、XML 索引、空間索引以及篩選的索引,IGNORE_DUP_KEY 不能設置爲 ON。
若要查看 IGNORE_DUP_KEY,請使用 sys.indexes。
在向後兼容的語法中,WITH IGNORE_DUP_KEY 等效於 WITH IGNORE_DUP_KEY = ON。
指定是否從新計算分發統計信息。默認值爲 OFF。
不會自動從新計算過期的統計信息。
啓用統計信息自動更新功能。
若要恢復統計信息自動更新,請將 STATISTICS_NORECOMPUTE 設置爲 OFF,或執行 UPDATE STATISTICS 但不包含 NORECOMPUTE 子句。
若是禁用分發統計信息的自動從新計算,可能會阻止查詢優化器爲涉及該表的查詢挑選最佳執行計劃。
指定在索引操做期間基礎表和關聯的索引是否可用於查詢和數據修改操做。默認值爲 OFF。
對於 XML 索引或空間索引,僅支持 ONLINE = OFF。若是 ONLINE 設置爲 ON,則會引起錯誤。
聯機索引操做僅在 SQL Server Enterprise Edition、Developer Edition 和 Evaluation Edition 中可用。
在索引操做期間不持有長期表鎖。在索引操做的主要階段,源表上只使用意向共享 (IS) 鎖。這樣,便可繼續對基礎表和索引進行查詢或更新。操做開始時,將對源對象保持極短期的共享 (S) 鎖。操做結束時,若是建立非彙集索引,將對源持有極短期的 S 鎖;當聯機建立或刪除彙集索引時,或者從新生成彙集或非彙集索引時,將獲取 SCH-M(架構修改)鎖。對本地臨時表建立索引時,ONLINE 不能設置爲 ON。
在索引操做期間應用表鎖。建立、從新生成或刪除彙集索引、空間索引或 XML 索引或者從新生成或刪除非彙集索引的脫機索引操做將得到對錶的架構修改 (Sch-M) 鎖。這樣能夠防止全部用戶在操做期間訪問基礎表。建立非彙集索引的脫機索引操做將對錶獲取共享 (S) 鎖。這樣能夠防止更新基礎表,但容許讀操做(如 SELECT 語句)。
有關詳細信息,請參閱聯機索引操做的工做方式。有關鎖的詳細信息,請參閱鎖模式。
索引(包括全局臨時表中的索引)能夠聯機從新生成,但如下索引除外:
若是表包含 LOB 數據類型,但這些列中沒有任何列在索引定義中用做鍵列或非鍵列,則能夠聯機從新生成非彙集索引。
指定是否容許行鎖。默認值爲 ON。
在訪問索引時容許使用行鎖。數據庫引擎肯定什麼時候使用行鎖。
不使用行鎖。
指定是否容許使用頁鎖。默認值爲 ON。
訪問索引時容許使用頁鎖。數據庫引擎肯定什麼時候使用頁鎖。
不使用頁鎖。
ALLOW_PAGE_LOCKS 設置爲 OFF 時,沒法從新組織索引。
在索引操做期間覆蓋「最大並行度」配置選項。有關詳細信息,請參閱 max degree of parallelism 選項。使用 MAXDOP 能夠限制在執行並行計劃的過程當中使用的處理器數量。最大數量爲 64 個處理器。
雖然從語法上講全部 XML 索引都支持 MAXDOP 選項,但對於空間索引或主 XML 索引,ALTER INDEX 當前只使用一個處理器。
max_degree_of_parallelism 能夠是:
取消生成並行計劃。
將並行索引操做中使用的最大處理器數量限制爲指定數量。
根據當前系統工做負荷使用實際的處理器數量或更少數量的處理器。
並行索引操做僅在 SQL Server Enterprise Edition、Developer Edition 和 Evaluation Edition 中可用。
爲指定的索引、分區號或分區範圍指定數據壓縮選項。選項以下所示:
不壓縮索引或指定的分區。
使用行壓縮來壓縮索引或指定的分區。
使用頁壓縮來壓縮索引或指定的分區。
有關壓縮的詳細信息,請參閱建立壓縮表和索引。
指定對其應用 DATA_COMPRESSION 設置的分區。若是索引未分區,則 ON PARTITIONS 參數將產生錯誤。若是不提供 ON PARTITIONS 子句,則 DATA_COMPRESSION 選項將應用於分區索引的全部分區。
能夠按如下方式指定 <partition_number_expression>:
<range> 能夠指定爲以單詞 TO 隔開的分區號,例如:ON PARTITIONS (6 TO 8)。
若要爲不一樣分區設置不一樣的數據壓縮類型,請屢次指定 DATA_COMPRESSION 選項,例如:
REBUILD WITH ( DATA_COMPRESSION = NONE ON PARTITIONS (1), DATA_COMPRESSION = ROW ON PARTITIONS (2, 4, 6 TO 8), DATA_COMPRESSION = PAGE ON PARTITIONS (3, 5) )
ALTER INDEX 不能用於對索引從新分區或將索引移到其餘文件組。此語句不能用於修改索引定義,如添加或刪除列,或更改列的順序。使用帶有 DROP_EXISTING 子句的 CREATE INDEX 執行這些操做。
未顯式指定選項時,則應用當前設置。例如,若是未在 REBUILD 子句中指定 FILLFACTOR 設置,將在從新生成過程當中使用系統目錄中存儲的填充因子值。若要查看當前索引選項設置,請使用 sys.indexes。
系統目錄中不存儲 ONLINE、MAXDOP 和 SORT_IN_TEMPDB 的值。除非在索引語句中指定,不然,將使用選項的默認值。
在多處理器計算機中,就像其餘查詢那樣,ALTER INDEX REBUILD 自動使用更多處理器來執行與修改索引相關聯的掃描和排序操做。運行 ALTER INDEX REORGANIZE 時,不管是否有 LOB_COMPACTION,「max degree of parallelism」值均爲單個線程化操做。有關詳細信息,請參閱配置並行索引操做。
若是索引所在的文件組脫機或設置爲只讀,則沒法從新組織或從新生成索引。若是指定了關鍵字 ALL,但有一個或多個索引位於脫機文件組或只讀文件組中,該語句將失敗。
從新生成索引將會刪除並從新建立索引。這將根據指定的或現有的填充因子設置壓縮頁來刪除碎片、回收磁盤空間,而後對連續頁中的索引行從新排序。若是指定 ALL,將刪除表中的全部索引,而後在單個事務中從新生成。沒必要預先刪除 FOREIGN KEY 約束。從新生成具備 128 個區或更多區的索引時,數據庫引擎延遲實際的頁釋放及其關聯的鎖,直到事務提交。有關詳細信息,請參閱刪除並從新生成大型對象。
從新生成或從新組織小索引不會減小碎片。小索引的頁面存儲在混合區中。混合區最多可由八個對象共享,所以在從新組織或從新生成小索引以後可能不會減小小索引中的碎片。
在早期版本的 SQL Server 中,您有時能夠從新生成非彙集索引來更正由硬件故障致使的不一致。在 SQL Server 2008 中,您仍然能夠經過脫機從新生成非彙集索引來糾正索引和彙集索引之間的這種不一致。可是,您不能經過聯機從新生成索引來糾正非彙集索引的不一致,由於聯機從新生成機制將會使用現有的非彙集索引做爲從新生成的基礎,所以仍存在不一致。相反,脫機從新生成索引將會強制掃描彙集索引(或堆),所以會刪除不一致。與早期版本同樣,建議經過從備份還原受影響的數據來從不一致狀態進行恢復;可是,您能夠經過脫機從新生成非彙集索引來糾正索引的不一致。
使用最少系統資源從新組織索引。經過對葉級頁以物理方式從新排序,使之與葉節點的從左到右的邏輯順序相匹配,進而對錶和視圖中的彙集索引和非彙集索引的葉級進行碎片整理。從新組織還會壓縮索引頁。壓縮基於現有的填充因子值。
若是指定 ALL,將從新組織表中的關係索引(包括彙集索引和非彙集索引)和 XML 索引。指定 ALL 時應用某些限制,請參閱「參數」部分的 ALL 定義。
禁用索引可防止用戶訪問該索引,對於彙集索引,還可防止用戶訪問基礎表數據。索引定義保留在系統目錄中。對視圖禁用非彙集索引或彙集索引會以物理方式刪除索引數據。禁用匯集索引將阻止對數據的訪問,但在刪除或從新生成索引以前,數據在 B 樹中一直保持未維護的狀態。
若是表位於事務複製發佈中,則沒法禁用任何與主鍵列關聯的索引。複製須要使用這些索引。若要禁用索引,必須先從發佈中刪除該表。
使用 ALTER INDEX REBUILD 語句或 CREATE INDEX WITH DROP_EXISTING 語句啓用索引。從新生成已禁用匯集索引不能在 ONLINE 選項設置爲 ON 時執行。
您能夠爲指定的索引設置選項 ALLOW_ROW_LOCKS、ALLOW_PAGE_LOCKS、IGNORE_DUP_KEY 和 STATISTICS_NORECOMPUTE,而不從新生成或從新組織該索引。修改的值當即應用於索引。
若是 ALLOW_ROW_LOCKS = ON 而且 ALLOW_PAGE_LOCK = ON,則當訪問索引時將容許行級別、頁級別和表級別的鎖。數據庫引擎將選擇相應的鎖,而且能夠將鎖從行鎖或頁鎖升級到表鎖。
若是 ALLOW_ROW_LOCKS = OFF 而且 ALLOW_PAGE_LOCK = OFF,則當訪問索引時只容許表級鎖。有關爲索引配置鎖定粒度的詳細信息,請參閱自定義索引的鎖定。
設置行鎖或頁鎖選項時,若是指定 ALL,這些設置將應用於全部索引。基礎表爲堆時,經過如下方式應用這些設置:
從新生成索引且 ONLINE 選項設置爲 ON 時,基礎對象、表和關聯的索引都可用於查詢和數據修改。更改過程當中,排他表鎖只保留很是短的時間。
從新組織索引始終聯機執行。該進程不長期保留鎖,所以,不阻塞正在運行的查詢或更新。
只有在執行如下操做時,才能對同一個表執行併發聯機索引操做:
同一時間執行的全部其餘聯機索引操做都將失敗。例如,您不能在同一個表中同時從新生成兩個索引或更多索引,也不能在同一個表中從新生成現有索引時建立新的索引。
有關詳細信息,請參閱聯機執行索引操做。
從新生成空間索引時,基礎用戶表在索引操做持續期間不可用,由於空間索引持有架構鎖。
對用戶表的某一列定義了空間索引時,沒法修改該表中的 PRIMARY KEY 約束。若要更改 PRIMARY KEY 約束,首先要刪除該表的每一個空間索引。修改 PRIMARY KEY 約束後,您能夠從新建立每一個空間索引。
在單個分區從新生成操做中,沒法指定任何空間索引。可是,您能夠在完整的分區從新生成過程當中指定空間索引。
若要更改特定於某個空間索引的選項(例如 BOUNDING_BOX 或 GRID),您可使用 CREATE SPATIAL INDEX 語句指定 DROP_EXISTING = ON,或刪除該空間索引並建立一個新的空間索引。有關示例,請參閱 CREATE SPATIAL INDEX (Transact-SQL)。
若要評估更改壓縮狀態將對錶、索引或分區有何影響,請使用 sp_estimate_data_compression_savings 存儲過程。
如下限制適用於已分區索引:
時,若是相應表具備非對齊索引,則沒法更改單個分區的壓縮設置。從新組織索引時,除了從新組織一個或多個索引外,默認狀況下還將壓縮彙集索引或基礎表中包含的大型對象數據類型 (LOB)。數據類型 image、text、ntext、varchar(max)、nvarchar(max)、varbinary(max) 和 xml 都是大型對象數據類型。壓縮此數據能夠改善磁盤空間使用狀況:
SET NOCOUNT ON DECLARE @Objectid INT, @Indexid INT,@schemaname VARCHAR(100),@tablename VARCHAR(300),@ixname VARCHAR(500),@avg_fip float,@command VARCHAR(4000) DECLARE IX_Cursor CURSOR FOR SELECT A.object_id,A.index_id,QUOTENAME(SS.NAME) AS schemaname,QUOTENAME(OBJECT_NAME(B.object_id,B.database_id))as tablename ,QUOTENAME(A.name) AS ixname,B.avg_fragmentation_in_percent AS avg_fip FROM sys.indexes A inner join sys.dm_db_index_physical_stats(DB_ID(),NULL,NULL,NULL,'LIMITED') AS B ON A.object_id=B.object_id and A.index_id=B.index_id INNER JOIN SYS.OBJECTS OS ON A.object_id=OS.object_id INNER JOIN sys.schemas SS ON OS.schema_id=SS.schema_id WHERE B.avg_fragmentation_in_percent>10 and B.page_count>20 AND A.index_id>0 AND A.IS_DISABLED<>1
--AND OS.name='book' ORDER BY tablename,ixname OPEN IX_Cursor FETCH NEXT FROM IX_Cursor INTO @Objectid,@Indexid,@schemaname,@tablename,@ixname,@avg_fip WHILE @@FETCH_STATUS=0 BEGIN IF @avg_fip<30.0 SET @command=N'ALTER INDEX '+@ixname+N' ON '+@schemaname+N'.'+ @tablename+N' REORGANIZE '; IF @avg_fip>=30.0 AND @Indexid=1 BEGIN IF EXISTS (SELECT * FROM SYS.columns WHERE OBJECT_ID=@Objectid AND max_length in(-1,16)) SET @command=N'ALTER INDEX '+@ixname+N' ON '+@schemaname+N'.'+ @tablename+N' REBUILD '; ELSE SET @command=N'ALTER INDEX '+@ixname+N' ON '+@schemaname+N'.'+ @tablename+N' REBUILD '+N' WITH (ONLINE = ON)'; END IF @avg_fip>=30.0 AND @Indexid>1 BEGIN IF EXISTS (SELECT * FROM SYS.index_columns IC INNER JOIN SYS.columns CS ON CS.OBJECT_ID=IC.OBJECT_ID AND CS.column_id=IC.column_id
WHERE IC.OBJECT_ID=@Objectid AND IC.index_id=@Indexid AND CS.max_length in(-1,16) ) SET @command=N'ALTER INDEX '+@ixname+N' ON '+@schemaname+N'.'+ @tablename+N' REBUILD '; ELSE SET @command=N'ALTER INDEX '+@ixname+N' ON '+@schemaname+N'.'+ @tablename+N' REBUILD '+N' WITH (ONLINE = ON)'; END --PRINT @command EXEC(@command) FETCH NEXT FROM IX_Cursor INTO @Objectid,@Indexid,@schemaname,@tablename,@ixname,@avg_fip END CLOSE IX_Cursor DEALLOCATE IX_Cursor
注意:該語句不適合全部人,你們根據本身的需求進行修改。
備註: 做者:pursuer.chen 博客:http://www.cnblogs.com/chenmh 本站點全部隨筆都是原創,歡迎你們轉載;但轉載時必須註明文章來源,且在文章開頭明顯處給明連接,不然保留追究責任的權利。 《歡迎交流討論》 |