【轉載】SqlServer 在線創建索引或在線重建索引(控制最大處理器數 、MAXDOP )
一、什么情況下需要重建索引
1、碎片過多(參考值:>20%)
索引碎片如何產生,請移步至《 T-SQL查詢高級—SQL Server索引中的碎片和填充因子》
2、填充度過低(參考值:<75%)
導致填充度過低的可能原因:①.有刪除 ②.有分區表 ③.聚集索引不是數字 ④.數據百萬以內,比較少

二、在線創建索引
如果你正在一個存在數據的表上創建新的索引,所有存在的行將會被索引作為CREATE INDEX語句的一部分。如果表非常大,索引過程將會花費些時間。索引過程對其他用戶會話的影響,基于SQL Server
是使用Offline模式還是Online模式。
默認,SQL Server以Offline模式執行索引操作,索引操作期間有表鎖請求。一個離線索引操作,創建、重建、或刪除一個聚集索引,或者重建或刪除一個非聚集索引,需要一個表上的架構修改(Sch-M)鎖。這阻止了所有用戶在操作期間訪問相應表。對一個離線索引操作,創建一個非聚集索引,在表上申請一個共享(S)鎖。他阻止了對相關表的更新但是允許讀操作,例如SELECT語句。
SQL Server Enterprise 版支持在線模式索引操作,其他的用戶會話就不會被影響。然而,SQL Server Express 版不支持在線模式,執行報錯。SQLServer2005以上版本支持在線索引創建和重建。
CREATE INDEX 索引名 ON 表名(字段) WITH (ONLINE = ON);
三、重建索引
ALTER INDEX 索引名 ON 表名或試圖名 REBUILD WITH (ONLINE = ON,MAXDOP = 4)
ONLINE:是否在線執行,減少重建過程中的鎖表 (執行時間延長)
MAXDOP :手動配置用于運行索引語句的最大處理器數
| 值 | 說明 |
| 0 | 指定服務器根據當前系統工作負荷確定所使用的 CPU 數目。這是默認值,還是推薦設置。 |
| 1 | 取消生成并行計劃。操作將以串行方式執行。 |
| 2-64 | 將處理器的數量限制為指定的值。根據當前工作負荷,可能使用較少的處理器。如果指定的值大于可用的 CPU 數量,將使用實際可用的 CPU 數量。 |
-- 查找數據庫碎片率大于40的索引信息 SELECT object_name(object_id) ,index_type_desc,alloc_unit_type_desc,avg_fragmentation_in_percent, fragment_count,avg_fragment_size_in_pages,page_count,record_count, avg_page_space_used_in_percent FROM sys.dm_db_index_physical_stats(DB_ID('數據庫名'), OBJECT_ID(''),NULL,NULL,'Sampled') WHERE avg_fragmentation_in_percent>40
mysql數據庫 SHOW TABLE STATUS LIKE '表名'; --查詢索引碎片 OPTIMIZE TABLE `表名`;--清理索引碎片,會鎖表
show OPEN TABLES where In_use > 0; 查看當前哪些表被鎖了
SHOW PROCESSLIST; 查看當前正在執行的sql語句 和執行狀態
在線整理索引,不鎖表https://blog.51cto.com/dadaman/1957229
Data_free為索引碎片字段
出現Table does not support optimize, doing recreate + analyze instead提示使用ALTER TABLE table.name ENGINE='InnoDB';
https://www.kafan.cn/edu/9810546.html
四、擴展筆記:
對于碎片的解決辦法 (引用自:宋沄劍 SQL Server索引中的碎片和填充因子)
基本上所有解決辦法都是基于對索引的重建和整理,只是方式不同
1.刪除索引并重建
這種方式并不好.在刪除索引期間,索引不可用.會導致阻塞發生。而對于刪除聚集索引,則會導致對應的非聚集索引重建兩次(刪除時重建,建立時再重建).雖然這種方法并不好,但是對于索引的整理最為有效
2.使用DROP_EXISTING語句重建索引
為了避免重建兩次索引,使用DROP_EXISTING語句重建索引,因為這個語句是原子性的,不會導致非聚集索引重建兩次,但同樣的,這種方式也會造成阻塞
3.如前面文章所示,使用ALTER INDEX REBUILD語句重建索引
使用這個語句同樣也是重建索引,但是通過動態重建索引而不需要卸載并重建索引.是優于前兩種方法的,但依舊會造成阻塞??梢酝ㄟ^ONLINE關鍵字減少鎖,但會造成重建時間加長.
4.使用ALTER INDEX REORGANIZE
這種方式不會重建索引,也不會生成新的頁,僅僅是整理,當遇到加鎖的頁時跳過,所以不會造成阻塞。但同時,整理效果會差于前三種.
總結:
1、如果數據庫當前有客戶不斷提交數據,使用第三種方式重建索引,親測不會對用戶插入和查詢數據有影響(重建索引后,數據庫變得更大)
2、如果數據庫當前沒有在線使用,可以先對數據庫進行收縮(選中數據庫-》任務-》收縮-》數據庫)減小數據庫大小后,再使用DBCC DBREINDEX('數據庫表名')重建索引,然后清除數據庫日志
--查看索引碎片情況 DBCC showcontig('數據庫表名') WITH ALL_INDEXES --整表重建索引方式,會鎖表,用戶不能插入數據 DBCC DBREINDEX('數據庫表名') --清理數據庫日志 DBCC SHRINKFILE(2)
//查詢索引id對應的字段名
SELECT a.name '索引名',a.indid '索引ID',c.name '表名',d.name '列名' FROM sysindexes a JOIN sysindexkeys b ON a.id=b.id AND a.indid=b.indid JOIN sysobjects c ON b.id=c.id JOIN syscolumns d ON b.id=d.id AND b.colid=d.colid WHERE a.indid NOT IN(0,255) AND c.name='要查詢的表名' --查指定表
1. 填充因子
在向索引中添加新行時容易發生分頁,不僅在頁拆分時會降低性能,還會導致產生過多的索引碎片(內部碎片)。
SQL Server允許在創建索引時指定一個填充因子,以便在索引的每個葉級頁上留出額外的間隙和保留一定百分比的空間,減少頁拆分的可能性。
填充因子的值是從 0 到 100 之間的百分比數值,指定在創建索引后對數據頁的填充比例。值為 0或100 時表示頁將填滿,所留出的存儲空間量最小。只有當不會對數據進行更改時(例如,在只讀表中)才會使用此設置。值越小則數據頁上的空閑空間越大,這樣可以減少在索引增長過程中對數據頁進行拆分的需要,但需要更多的存儲空間。當表中數據會頻繁發生更改時,這種設置更為適當。
2. 通過腳本修改填充因子并重建索引
ALTER INDEX IX_person2_UserID ON person2 REBUILD WITH (FILLFACTOR = 60)
http://www.rzrgm.cn/hanmos/archive/2011/03/28/1998054.html
一般的填充因子設置策略:
數據變化越頻繁,填充因子越小
數據越少變化,填充因子越大
對于數據不變化的表,填充因子設置為100
原文地址:
http://www.rzrgm.cn/hydor/p/5254292.html
http://blog.51cto.com/ultrasql/1737335
https://cloud.tencent.com/developer/article/1342498
設置定時執行步驟
(1)啟動【sql server Management Studio】,在【對象資源管理器】窗口里選擇【管理】——【維護計劃】選項。
(2)右擊【維護計劃】,在彈出的快捷菜單里選擇【維護計劃向導】選項,彈出如圖所示的【維護計劃向導】對話框,單擊【下一步】按鈕
(3)彈出如圖所示【選擇目標服務器】對話框,在【名稱】文本框里可以輸入維護計劃的名稱;在【說明】文本框里可以輸入維護計劃的說明文字;【在服務器】文本框里可以輸入要使用的服務器名;最后選擇正確的身份證信息,單擊【下一步】按鈕。
(4)彈出如圖所示【選擇維護任務】對話框,在該對話框中可以選擇執行sql維護任務,插入執行存儲過程語句
(5)制定任務執行計劃
不指定sql語句全局方法

重新生成索引任務,可不鎖表和鎖表
https://docs.microsoft.com/zh-cn/sql/relational-databases/maintenance-plans/rebuild-index-task-maintenance-plan?view=sql-server-ver15
重新組織索引任務,不鎖表
https://docs.microsoft.com/zh-cn/sql/relational-databases/maintenance-plans/reorganize-index-task-maintenance-plan?view=sql-server-ver15
http://www.rzrgm.cn/flysun0311/archive/2013/12/05/3459451.html
alter index來rebuild和reorganize索引來清除碎片,rebuild能夠完全清除碎片,但是reorganize卻不能。
online模式下
rebuild index會復制舊索引來新建索引,此時舊的索引依然可以被讀取和修改,但是所以在舊索引上的修改都會同步更新到新索引下。中間會有一些沖突解決機制,具體參考Online Index Operations 里面的Build Phase這一章節。然后在rebuild這個過程完整的時候,會對table上鎖一段時間,在這段時間里會用新索引來替換舊索引,當這個過程完成以后再釋放table上面的鎖。如果索引列包含 LOB對象的話,在SQL Server 2005/2008/R2中rebuild index online會失敗。在sql server 2012中,即使索引列包含LOB對象,也可以rebuild index online了,可以參考 Online Index Operations for indexes containing LOB columns.
offline模式下
rebuilde index會對table上鎖,所有對這個table的讀寫操作都會被阻塞,在這期間新索引根據舊索引來創建,其實就是一個復制的過程,但是新索引沒有碎片,最后使用新索引替換舊索引。當rebuild整個過程完成以后,table上面的鎖才會被釋放。

浙公網安備 33010602011771號