共用方式為


重新組織及重建索引

本主題描述如何使用 SQL Server Management Studio 或 Transact-SQL,在 SQL Server 2014 中重新組織或重建片段索引。 每當對基礎數據進行插入、更新或刪除作業時,SQL Server Database Engine 會自動維護索引。 經過一段時間后,這些修改可能會導致索引中的資訊分散在資料庫中(分散)。 當索引包含依據鍵值排序的頁面,而該排序不符合資料檔案中的實際順序時,就會出現碎片化。 大量分散的索引可能會降低查詢效能,並導致應用程式回應緩慢。

您可以透過重新組織或重建索引來修復索引碎片化。 對於以數據分割配置為基礎的分割索引,您可以在完整的索引或索引的單一分割區上使用這些方法之一。 重建索引會刪除並重新建立索引。 這會移除片段;根據指定的或現有的填滿因數設定壓縮頁面來收回磁碟空間,以及重新排序連續頁面中的索引資料列。 指定 ALL 時,數據表上的所有索引都會卸除,並在單一交易中重建。 重新組織索引所用的系統資源最少。 它會實際重新排序分葉層級的頁面,使它們由左至右符合分葉節點的邏輯順序,以重新組織資料表和檢視表之叢集和非叢集索引的分葉層級。 重新組織也會壓縮索引頁面。 壓縮是以現有填滿因數值為基礎。

本主題內容

開始之前

偵測碎片化

決定要使用的重組方法的第一個步驟是分析索引,以判斷片段的程度。 藉由使用系統函數 sys.dm_db_index_physical_stats,您可以偵測特定索引是否有碎片,以及資料表或索引檢視表上的所有索引、資料庫中的所有索引,或所有資料庫中的所有索引是否有碎片。 針對分割索引,sys.dm_db_index_physical_stats也會提供每個分割區的碎片資訊。

sys.dm_db_index_physical_stats函式傳回的結果集包含下列數據行。

資料行 說明
平均碎片率百分比 邏輯碎片的百分比(指索引中錯位的頁面)。
碎片數 索引中碎片的數量(實際上連續的葉頁)。
avg_fragment_size_in_pages 索引中一個片段的平均頁數。

已知片段程度之後,請使用下表來判斷更正片段的最佳方法。

avg_fragmentation_in_percent 百分比值 更正聲明
> 5% 和 < = 30% ALTER INDEX REORGANIZE 用於優化索引結構。
> 30% ALTER INDEX REBUILD WITH 「ONLINE = ON」 1

1 重建索引可以在在線或離線執行。 重新組織索引一律會在在線執行。 若要達到類似重新組織選項的可用性,您應該在線重建索引。

小提示

這些值提供粗略的指導方針,幫助判斷您應該在 ALTER INDEX REORGANIZEALTER INDEX REBUILD 之間切換的點。 不過,實際值可能會因案例而異。 請務必進行實驗,以判斷環境的最佳閾值。 例如,如果指定的索引主要用於掃描作業,則移除片段可以改善這些作業的效能。 針對主要用於搜尋作業的索引,效能優點較不明顯。 同樣地,移除堆積中的片段(沒有叢集索引的數據表)對於非叢集索引掃描作業特別有用,但在查閱作業中幾乎沒有作用。

這些命令通常不應該解決非常低的片段層級(小於5%),因為移除如此少量的片段的好處幾乎總是大大超過重新組織或重建索引的成本。

備註

重建或重新組織小型索引通常不會減少碎片化。 小型索引的頁面有時會儲存在混合區域內。 混合範圍最多可由八個物件所共用,所以當重新組織或重建索引之後,小型索引中的片段可能不會減少。

索引重組考慮

在某些情況下,如果非叢集索引記錄中包含的實體或邏輯標識碼需要變更,重建叢集索引會自動重建參考叢集索引鍵的任何非叢集索引。

導致在資料表上自動重建所有非叢集索引的情境:

  • 在數據表上建立叢集索引
  • 拿掉叢集索引,導致數據表儲存為堆積
  • 變更叢集鍵以包含或排除欄位

不需要在資料表上自動重建所有非叢集索引的案例:

  • 重建唯一的叢集索引
  • 重建非唯一叢集索引
  • 變更索引架構,例如將分割區配置套用至叢集索引,或將叢集索引移至不同的檔案群組

限制與制約

索引具有超過128個維度,這些索引被分為兩個不同的階段進行重建:邏輯和實體。 在邏輯階段中,索引所使用的現有配置單位將以取消配置標示,並複製和排序資料列,然後移到所建立的新配置單位以儲存重建索引。 在物理階段中,先前被標記為取消配置的配置單元會在背景的短期交易中實體卸除,且不需要許多鎖定。 如需範圍的詳細資訊,請參閱 頁面和範圍架構指南

ALTER INDEX REORGANIZE語句需要包含索引的數據檔具有可用空間,因為作業只能配置相同檔案上的暫存工作頁面,而不是檔案群組中的另一個檔案。 因此,雖然檔案群組可能有可用的免費頁面,但使用者仍可能會遇到錯誤 1105: Could not allocate space for object '###' in database '###' because the '###' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.

在具有超過 1,000 個數據分割的數據表上建立和重建不對齊的索引是可行的,但不建議這麼做。 此做法可能會導致在作業期間效能降低或耗用過多記憶體。

如果索引所在的檔案群組離線或設定為唯讀,則無法重新組織或重建索引。 指定 關鍵詞 ALL 且一或多個索引位於離線或唯讀檔案群組中時,語句會失敗。

安全

權限

必須具備資料表或檢視的 ALTER 權限。 使用者必須是 系統管理員 固定伺服器角色的成員,或是 db_ddladmindb_owner 固定資料庫角色的成員。

使用 SQL Server Management Studio

檢查索引的碎片化程度

  1. 在 [物件總管] 中,展開包含您要檢查索引片段之數據表的資料庫。

  2. 展開 [資料表] 資料夾。

  3. 展開您要檢查索引破碎程度的資料表。

  4. 展開 [索引] 資料夾。

  5. 以滑鼠右鍵按下您要檢查片段的索引,然後選取 [ 屬性]。

  6. [選取頁面] 底下,選取 [片段]。

    [ 片段 ] 頁面上提供下列資訊:

    頁面完整度
    以百分比表示索引頁的平均完整度。 100% 表示索引頁已完全滿。 50% 表示,平均而言,每個索引頁都已滿半。

    總碎片化
    邏輯片段百分比。 這表示索引中未依序儲存的頁面數目。

    平均數據列大小
    分葉層級數據列的平均大小。

    深度
    索引中的層級數目,包括分葉層級。

    轉送的記錄
    堆積中具有指向另一個數據位置之正向指標的記錄數目。 (當沒有足夠的空間將新數據列儲存在原始位置時,就會在更新期間發生此狀態。

    幽靈列
    標示為已刪除但尚未移除的數據列數目。 當伺服器不忙碌時,清除線程將會移除這些數據列。 這個值不包含因為未完成快照集隔離交易而保留的數據列。

    索引類型
    索引的類型。 可能的值為 叢集索引非叢集索引主要 XML。 數據表也可以儲存為堆積(不含索引),但無法開啟此索引屬性頁面。

    分葉層級數據列
    葉子層級列數。

    數據列大小上限
    葉層級行列大小上限。

    數據列大小下限
    最小分葉層級的數據列大小。

    頁面
    數據頁總數。

    分割區識別碼
    包含索引之 B 樹的分割區 ID。

    版本幽靈列
    由於未處理的快照隔離交易而保留的准刪除記錄數目。

使用 Transact-SQL

檢查索引的片段

  1. 物件總管中,連線到資料庫引擎實例。

  2. 在標準列上,按一下 [新增查詢]

  3. 複製下列範例並將其貼到查詢視窗中,然後按一下 [執行]

    USE AdventureWorks2012;  
    GO  
    -- Find the average fragmentation percentage of all indexes  
    -- in the HumanResources.Employee table.   
    SELECT a.index_id, name, avg_fragmentation_in_percent  
    FROM sys.dm_db_index_physical_stats (DB_ID(N'AdventureWorks2012'), OBJECT_ID(N'HumanResources.Employee'), NULL, NULL, NULL) AS a  
        JOIN sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id;   
    GO  
    

    上述語句可能會傳回類似下列的結果集。

    index_id    name                                                  avg_fragmentation_in_percent  
    ----------- ----------------------------------------------------- ----------------------------  
    1           PK_Employee_BusinessEntityID                          0  
    2           IX_Employee_OrganizationalNode                        0  
    3           IX_Employee_OrganizationalLevel_OrganizationalNode    0  
    5           AK_Employee_LoginID                                   66.6666666666667  
    6           AK_Employee_NationalIDNumber                          50  
    7           AK_Employee_rowguid                                   0  
    
    (6 row(s) affected)  
    

如需詳細資訊,請參閱 sys.dm_db_index_physical_stats (Transact-SQL)

使用 SQL Server Management Studio

重新組織或重建索引

  1. 在 [物件總管] 中,展開包含您要重新組織索引之數據表的資料庫。

  2. 展開 [資料表] 資料夾。

  3. 展開您要進行索引重組的資料表。

  4. 展開 [索引] 資料夾。

  5. 以滑鼠右鍵按一下您要重新組織的索引,然後選取 [重新組織]

  6. 在 [ 重新組織索引 ] 對話框中,確認正確的索引位於 重新組織 方格中,然後按兩下 [ 確定]。

  7. 選取 [壓縮大型物件欄位資料] 核取方塊,以指定壓縮所有包含大型物件 (LOB) 資料的頁面。

  8. 按一下 [確定]。

重新組織數據表中的所有索引

  1. 在 [物件總管] 中,展開包含您要重新整理索引的資料表所在的資料庫。

  2. 展開 [資料表] 資料夾。

  3. 請展開您要重新整理索引的資料表。

  4. 以滑鼠右鍵按一下 [索引] 資料夾,並選取 [全部重新組織]

  5. [重新組織索引] 對話方塊中,確認 [要重新組織的索引] 方格中有正確索引。 若要從 [要重新組織的索引] 方格中移除索引,請選取索引,然後按下 DELETE 鍵。

  6. 選取 [壓縮大型物件欄位資料] 核取方塊,以指定壓縮所有包含大型物件 (LOB) 資料的頁面。

  7. 按一下 [確定]。

重建索引

  1. 在 [物件總管] 中,展開包含您要重新組織索引之數據表的資料庫。

  2. 展開 [資料表] 資料夾。

  3. 展開您要進行索引重組的資料表。

  4. 展開 [索引] 資料夾。

  5. 以滑鼠右鍵按一下您要重新組織的索引,然後選取 [重新組織]

  6. 在 [ 重建索引 ] 對話框中,確認正確的索引位於 [要重建的索引 ] 方格中,然後按兩下 [ 確定]。

  7. 選取 [壓縮大型物件欄位資料] 核取方塊,以指定壓縮所有包含大型物件 (LOB) 資料的頁面。

  8. 按一下 [確定]。

使用 Transact-SQL

重新組織經過碎片整理的索引

  1. 物件總管中,連線到資料庫引擎實例。

  2. 在標準列上,按一下 [新增查詢]

  3. 複製下列範例並將其貼到查詢視窗中,然後按一下 [執行]

    USE AdventureWorks2012;   
    GO  
    -- Reorganize the IX_Employee_OrganizationalLevel_OrganizationalNode index on the HumanResources.Employee table.   
    
    ALTER INDEX IX_Employee_OrganizationalLevel_OrganizationalNode ON HumanResources.Employee  
    REORGANIZE ;   
    GO  
    

重新組織數據表中的所有索引

  1. 物件總管中,連線到資料庫引擎實例。

  2. 在標準列上,按一下 [新增查詢]

  3. 複製下列範例並將其貼到查詢視窗中,然後按一下 [執行]

    USE AdventureWorks2012;   
    GO  
    -- Reorganize all indexes on the HumanResources.Employee table.  
    ALTER INDEX ALL ON HumanResources.Employee  
    REORGANIZE ;   
    GO  
    

重建重組的索引

  1. 物件總管中,連線到資料庫引擎實例。

  2. 在標準列上,按一下 [新增查詢]

  3. 複製下列範例並將其貼到查詢視窗中,然後按一下 [執行] 。 此範例會重建數據表上的 Employee 單一索引。

    USE AdventureWorks2012;
    GO
    ALTER INDEX PK_Employee_BusinessEntityID ON HumanResources.Employee
    REBUILD;
    GO
    

重建數據表中的所有索引

  1. 物件總管中,連線到資料庫引擎實例。

  2. 在標準列上,按一下 [新增查詢]

  3. 將下列範例複製並貼到查詢 中:此範例會指定 關鍵字 ALL。 這會重建與數據表相關聯的所有索引。 指定三個選項。

    USE AdventureWorks2012;
    GO
    ALTER INDEX ALL ON Production.Product
    REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON,
                  STATISTICS_NORECOMPUTE = ON);
    GO
    

如需詳細資訊,請參閱 ALTER INDEX (Transact-SQL)

另請參閱

Microsoft SQL Server 2000 索引重組最佳做法