2009-07-06 32 views
12

Có ai có thể cung cấp kịch bản để xây dựng lại và lập chỉ mục lại chỉ mục phân mảnh khi 'avg_fragmentation_in_percent' vượt quá các giới hạn nhất định (tốt hơn nếu con trỏ không được sử dụng)?Kịch bản để xây dựng lại và tái lập chỉ mục phân mảnh?

+1

Tại sao không? Bất kỳ ai cũng có thể chọn đặt bất kỳ câu hỏi nào mà họ hỏi một câu hỏi Wiki. Nó tránh mất điểm rep. –

+0

@Savitha: phần nào là vấn đề? Tôi không ngay lập tức chắc chắn cách bạn sẽ thực hiện thao tác bằng con trỏ. Bạn đang tìm kiếm một kịch bản để phát hiện tỷ lệ phần trăm và sau đó xây dựng lại? Bạn đã kiểm tra hướng dẫn sử dụng cho các tùy chọn chưa? Các báo cáo có sẵn là gì? Bạn có phải xác định chi tiết chỉ mục không? Có câu lệnh ALTER INDEX nào không? –

+0

@ Jonathan Leffler, nhưng đây là một câu hỏi hợp pháp tốt với ít rủi ro bị bỏ phiếu. ít người xem wiki và/hoặc muốn trả lời cho 0 điểm. –

Trả lời

18

Để xây dựng lại sử dụng:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REBUILD 

hoặc tổ chức lại sử dụng:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REORGANIZE 

Tổ chức lại nên được sử dụng với giá thấp (< 30%) phân mảnh nhưng chỉ xây dựng lại (mà nặng đến cơ sở dữ liệu) cắt giảm phân mảnh xuống 0%.
Để biết thêm thông tin, xem https://msdn.microsoft.com/en-us/library/ms189858.aspx

6

Đây là kịch bản biến đổi mà tôi mất từ ​​http://www.foliotek.com/devblog/sql-server-optimization-with-index-rebuilding mà tôi thấy hữu ích để trả lời ở đây. Mặc dù nó sử dụng một con trỏ và tôi biết vấn đề chính với con trỏ là nó có thể dễ dàng chuyển đổi thành một phiên bản con trỏ ít hơn.

Tài liệu được ghi chép kỹ lưỡng và bạn có thể dễ dàng đọc qua và sửa đổi theo nhu cầu của mình.

IF OBJECT_ID('tempdb..#work_to_do') IS NOT NULL 
     DROP TABLE tempdb..#work_to_do 

BEGIN TRY 
--BEGIN TRAN 

use yourdbname 

-- Ensure a USE statement has been executed first. 

    SET NOCOUNT ON; 

    DECLARE @objectid INT; 
    DECLARE @indexid INT; 
    DECLARE @partitioncount BIGINT; 
    DECLARE @schemaname NVARCHAR(130); 
    DECLARE @objectname NVARCHAR(130); 
    DECLARE @indexname NVARCHAR(130); 
    DECLARE @partitionnum BIGINT; 
    DECLARE @partitions BIGINT; 
    DECLARE @frag FLOAT; 
    DECLARE @pagecount INT; 
    DECLARE @command NVARCHAR(4000); 

    DECLARE @page_count_minimum SMALLINT 
    SET @page_count_minimum = 50 

    DECLARE @fragmentation_minimum FLOAT 
    SET @fragmentation_minimum = 30.0 

-- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function 
-- and convert object and index IDs to names. 

    SELECT object_id AS objectid , 
      index_id AS indexid , 
      partition_number AS partitionnum , 
      avg_fragmentation_in_percent AS frag , 
      page_count AS page_count 
    INTO #work_to_do 
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 
              'LIMITED') 
    WHERE avg_fragmentation_in_percent > @fragmentation_minimum 
      AND index_id > 0 
      AND page_count > @page_count_minimum; 

IF CURSOR_STATUS('global', 'partitions') >= -1 
BEGIN 
PRINT 'partitions CURSOR DELETED' ; 
    CLOSE partitions 
    DEALLOCATE partitions 
END 
-- Declare the cursor for the list of partitions to be processed. 
    DECLARE partitions CURSOR LOCAL 
    FOR 
     SELECT * 
     FROM #work_to_do; 

-- Open the cursor. 
    OPEN partitions; 

-- Loop through the partitions. 
    WHILE (1 = 1) 
     BEGIN; 
      FETCH NEXT 
FROM partitions 
INTO @objectid, @indexid, @partitionnum, @frag, @pagecount; 

      IF @@FETCH_STATUS < 0 
       BREAK; 

      SELECT @objectname = QUOTENAME(o.name) , 
        @schemaname = QUOTENAME(s.name) 
      FROM sys.objects AS o 
        JOIN sys.schemas AS s ON s.schema_id = o.schema_id 
      WHERE o.object_id = @objectid; 

      SELECT @indexname = QUOTENAME(name) 
      FROM sys.indexes 
      WHERE object_id = @objectid 
        AND index_id = @indexid; 

      SELECT @partitioncount = COUNT(*) 
      FROM sys.partitions 
      WHERE object_id = @objectid 
        AND index_id = @indexid; 

      SET @command = N'ALTER INDEX ' + @indexname + N' ON ' 
       + @schemaname + N'.' + @objectname + N' REBUILD'; 

      IF @partitioncount > 1 
       SET @command = @command + N' PARTITION=' 
        + CAST(@partitionnum AS NVARCHAR(10)); 

      EXEC (@command); 
      --print (@command); //uncomment for testing 

      PRINT N'Rebuilding index ' + @indexname + ' on table ' 
       + @objectname; 
      PRINT N' Fragmentation: ' + CAST(@frag AS VARCHAR(15)); 
      PRINT N' Page Count: ' + CAST(@pagecount AS VARCHAR(15)); 
      PRINT N' '; 
     END; 

-- Close and deallocate the cursor. 
    CLOSE partitions; 
    DEALLOCATE partitions; 

-- Drop the temporary table. 
    DROP TABLE #work_to_do; 
--COMMIT TRAN 

END TRY 
BEGIN CATCH 
--ROLLBACK TRAN 
    PRINT 'ERROR ENCOUNTERED:' + ERROR_MESSAGE() 
END CATCH 
5

Hai giải pháp: Một cách đơn giản và nâng cao hơn.

Giới thiệu

Có hai giải pháp có sẵn để bạn tùy thuộc vào mức độ nghiêm trọng của vấn đề của bạn

Replace with giá trị của riêng mình, như sau:

  • Thay XXXMYINDEXXXX với tên của một chỉ số.
  • Thay thế XXXMYTABLEXXX bằng tên của bảng.
  • Thay thế XXXDATABASENAMEXXX bằng tên của cơ sở dữ liệu.

Giải pháp 1. Indexing

Rebuild tất cả các chỉ số cho một bảng trong chế độ ẩn

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD 

Rebuild một chỉ số chỉ định cho một bảng trong chế độ offline

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD 

Giải pháp 2. Phân mảnh

Phân mảnh là một vấn đề trong các bảng thường xuyên có các mục nhập được thêm vào và bị xóa.

Kiểm tra phân mảnh tỷ lệ

SELECT 
    ips.[index_id] , 
    idx.[name] , 
    ips.[avg_fragmentation_in_percent] 
FROM  
    sys.dm_db_index_physical_stats(DB_ID(N'XXXMYDATABASEXXX'), OBJECT_ID(N'XXXMYTABLEXXX'), NULL, NULL, NULL) AS [ips] 
    INNER JOIN sys.indexes AS [idx] ON [ips].[object_id] = [idx].[object_id] AND [ips].[index_id] = [idx].[index_id] 

Phân mảnh 5..30%

Nếu giá trị phân mảnh lớn hơn 5%, nhưng ít hơn 30% sau đó nó là giá trị sắp xếp chỉ mục.

Tổ chức lại tất cả các chỉ số cho một bảng

ALTER INDEX ALL ON XXXMYTABLEXXX REORGANIZE 

Reorganize một số quy định cho một bảng

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REORGANIZE 

Phân mảnh 30% +

Nếu giá trị phân mảnh là 30% hoặc lớn hơn thì nó đáng để xây dựng lại rồi các chỉ mục trong chế độ trực tuyến.

Rebuild tất cả các chỉ số trong chế độ trực tuyến với một bảng

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD WITH (ONLINE = ON) 

Rebuild một số quy định trong chế độ trực tuyến với một bảng

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD WITH (ONLINE = ON) 
Các vấn đề liên quan