Vra

In die SUIDWES reëls om beter SQL Server Databasis daar is'n voorbeeld van'n volledige databasis onderhoud plan: SMW.In die voorbeeld wat hulle hardloop beide'n Herorganiseer Indeks en dan'n Herbou Indeks en dan Werk Statistiek.Is daar enige punt van hierdie?Ek het gedink Herorganiseer Indeks is'n vinnig, maar minder effektiewe weergawe van die Herbou Indeks?en wat'n indeks herbou sou ook werk om die statistieke outomaties (op die gegroepeer indeks ten minste).

Was dit nuttig?

Oplossing

Doen 'n REORGANIZE en dan 'n REBUILD op dieselfde indekse is nutteloos, as enige veranderinge deur die REORGANIZE verlore sal gaan deur die doen van die REBUILD.

Erger as dit is dat in die instandhouding plan diagram van SMW, dit voer 'n SHRINK eerste, wat die indekse fragmente as 'n newe-effek van die manier waarop dit stel ruimte. Dan ken die REBUILD meer ruimte om die databasis lêers weer as werkruimte tydens die REBUILD operasie.

  • REORGANIZE is 'n aanlyn aksie wat blaar bladsye in 'n gegroepeer of nie-gegroepeer indeks bladsy defragments deur bladsy behulp bietjie ekstra werkruimte.

  • REBUILD is 'n aanlyn operasie in Enterprise uitgawes, op die regte pad in ander uitgawes, en gebruik soveel ekstra werkruimte weer as die indeks grootte. Dit skep 'n nuwe kopie van die indeks en dan daal die ou een, dus om ontslae te raak van fragmentasie. Statistiek is recomputed by verstek as deel van hierdie aksie, maar wat kan wees afgeskakel.

reorganiseren en herbou indekse vir meer inligting.

Moenie SHRINK behalwe met die opsie TRUNCATEONLY en selfs dan as die lêer weer sal groei dan moet jy hard dink oor die vraag of dit nodig is:

sqlservercentral_SHRINKFILE

Ander wenke

Die herorganiseer en herbou is verskillende dinge.

herorganiseer: dit is 'n defrag vir indekse. Neem die bestaande indeks (es) en defragments die bestaande bladsye. Maar as die bladsye is nie in 'n aangrensende wyse, hulle bly soos voorheen. Slegs die inhoud van die bladsye verander.

Herbou: eintlik is dit daal die indeks en rebuild dit van nuuts af. Dit beteken dat jy 'n heeltemal nuwe indeks sal kry, met gedefragmenteerd en aangrensende bladsye.

Verder met herbou kan jy verdeling of lêer groepe verander, maar met herorganiseer jy kan nie net die hele indeks, maar ook net een partisie van die indeks defrag.

Die update statistieke is 'n outomatiese op gegroepeer indekse, maar nie op die nie-gegroepeer kinders.

Voor oorweging van die instandhouding van indekse, dit is belangrik om te beantwoord twee vrae:

  1. Wat is die graad van fragmentasie?
  2. Wat is die gepaste optrede?Herorganiseer of herbou?

Soos beskryf in hierdie artikel http://solutioncenter.apexsql.com/why-when-and-how-to-rebuild-and-reorganize-sql-server-indexes/, en om jou te help bepaal of jy moet verrig indeks herbou of indeks herorganisasie, verstaan asseblief die volgende:

  • Indeks herorganisasie is'n proses waar die SQL Server gaan deur middel van die bestaande indeks, en reinig dit.Indeks herbou is'n swaar proses waar indeks is geskrap en dan herskep van nuuts af met'n heeltemal nuwe struktuur, vry van alle opgestapel fragmente en leë ruimte bladsye.

  • Terwyl die indeks herorganisasie is'n suiwer opruim operasie wat laat stelsel staat as wat dit is sonder sluit-uit geraak tafels en menings, die herbou proses slotte geraak tafel vir die hele herbou tydperk, wat kan lei in'n lang af-tye wat kan nie aanvaarbaar wees in sommige omgewings.Met dit in gedagte, is dit duidelik dat die indeks herbou is'n proses met'n sterker' oplossing, maar dit kom met'n prys – moontlik lang slotte op geraak word geïndekseer tafels.

Aan die ander kant, indeks herorganisasie is'n "liggewig" - proses wat sal die oplossing van die fragmentasie in'n minder doeltreffende manier – sedert skoongemaak indeks sal altyd tweede na die nuwe een ten volle gemaak van nuuts af.Maar die herstrukturering van die indeks is baie beter van die doeltreffendheid oogpunt, aangesien dit nie die slot geraak word geïndekseer tafel tydens die verloop van die operasie.

Die bogenoemde artikel verduidelik ook hoe om te herorganiseer en te herbou indekse gebruik SSMS, T-SQL (te herorganiseer/herbou indekse in'n tabel) en'n 3de party hulpmiddel genaamd ApexSQL Rugsteun.

Wanneer doen 'n reorg van 'n indeks, as die indeks is versprei oor twee of meer fisiese lêers die data sal slegs defragged binne die data lêer. Bladsye is nie verskuif van die een data lêer na 'n ander.

Wanneer die indeks is in 'n enkele lêer die reorg en indekseer sal dieselfde eindresultaat het.

'N paar keer die reorg sal vinniger wees, en 'n paar keer die indekseer sal vinniger wees, afhangende van hoe gefragmenteerde die indeks is. Die minder gefragmenteerde die indeks dan 'n reorg sal vinniger, hoe meer gefragmenteerd hoe stadiger sal die reorg sal wees, maar hoe vinniger 'n indekseer sal wees.

Wat presies Biri gesê. Hier is hoe ek 'n hele databasis sal indekseer:

EXEC [sp_MSforeachtable] @command1="RAISERROR('DBCC DBREINDEX(''?'') ...',10,1) WITH NOWAIT DBCC DBREINDEX('?')"

Ek gebruik hierdie SP

CREATE PROCEDURE dbo.[IndexRebuild]
AS 
DECLARE @TableName NVARCHAR(500);
DECLARE @SQLIndex NVARCHAR(MAX);
DECLARE @RowCount INT;
DECLARE @Counter INT;

DECLARE @IndexAnalysis TABLE
    (
      AnalysisID INT IDENTITY(1, 1)
                     NOT NULL
                     PRIMARY KEY ,
      TableName NVARCHAR(500) ,
      SQLText NVARCHAR(MAX) ,
      IndexDepth INT ,
      AvgFragmentationInPercent FLOAT ,
      FragmentCount BIGINT ,
      AvgFragmentSizeInPages FLOAT ,
      PageCount BIGINT
    )

BEGIN
    INSERT  INTO @IndexAnalysis
            SELECT  [objects].name ,
                    'ALTER INDEX [' + [indexes].name + '] ON ['
                    + [schemas].name + '].[' + [objects].name + '] '
                    + ( CASE WHEN (   [dm_db_index_physical_stats].avg_fragmentation_in_percent >= 20
                                    AND [dm_db_index_physical_stats].avg_fragmentation_in_percent < 40
                                  ) THEN 'REORGANIZE'
                             WHEN [dm_db_index_physical_stats].avg_fragmentation_in_percent > = 40
                             THEN 'REBUILD'
                        END ) AS zSQL ,
                    [dm_db_index_physical_stats].index_depth ,
                    [dm_db_index_physical_stats].avg_fragmentation_in_percent ,
                    [dm_db_index_physical_stats].fragment_count ,
                    [dm_db_index_physical_stats].avg_fragment_size_in_pages ,
                    [dm_db_index_physical_stats].page_count
            FROM    [sys].[dm_db_index_physical_stats](DB_ID(), NULL, NULL,
                                                       NULL, 'LIMITED') AS   [dm_db_index_physical_stats]
                    INNER JOIN [sys].[objects] AS [objects] ON (   [dm_db_index_physical_stats].[object_id] = [objects].[object_id] )
                    INNER JOIN [sys].[schemas] AS [schemas] ON ( [objects].[schema_id]  = [schemas].[schema_id] )
                    INNER JOIN [sys].[indexes] AS [indexes] ON (  [dm_db_index_physical_stats].[object_id] = [indexes].[object_id]
                                                          AND  [dm_db_index_physical_stats].index_id = [indexes].index_id
                                                          )
            WHERE   index_type_desc <> 'HEAP'
                    AND [dm_db_index_physical_stats].avg_fragmentation_in_percent > 20
END

SELECT  @RowCount = COUNT(AnalysisID)
FROM    @IndexAnalysis

SET @Counter = 1
WHILE @Counter <= @RowCount 
    BEGIN

        SELECT  @SQLIndex = SQLText
        FROM    @IndexAnalysis
        WHERE   AnalysisID = @Counter

        EXECUTE sp_executesql @SQLIndex

        SET @Counter = @Counter + 1

    END
 GO

en skep 'n werk wat hierdie SP elke week uit te voer.

Selfs beter is:

EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REINDEX'

of

EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REORGANIZE'

My twee sent ... Hierdie metode volg die spec uiteengesit op tegnologie netto: http://technet.microsoft.com/en-us/library/ms189858 (v = sql.105) Aspx

USE [MyDbName]
GO

SET ANSI_NULLS OFF
GO

SET QUOTED_IDENTIFIER OFF
GO

CREATE PROCEDURE [maintenance].[IndexFragmentationCleanup]
AS
DECLARE @reIndexRequest VARCHAR(1000)

DECLARE reIndexList CURSOR
FOR
SELECT INDEX_PROCESS
FROM (
    SELECT CASE 
            WHEN avg_fragmentation_in_percent BETWEEN 5
                    AND 30
                THEN 'ALTER INDEX [' + i.NAME + '] ON [' + t.NAME + '] REORGANIZE;'
            WHEN avg_fragmentation_in_percent > 30
                THEN 'ALTER INDEX [' + i.NAME + '] ON [' + t.NAME + '] REBUILD with(ONLINE=ON);'
            END AS INDEX_PROCESS
        ,avg_fragmentation_in_percent
        ,t.NAME
    FROM sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, NULL) AS a
    INNER JOIN sys.indexes AS i ON a.object_id = i.object_id
        AND a.index_id = i.index_id
    INNER JOIN sys.tables t ON t.object_id = i.object_id
    WHERE i.NAME IS NOT NULL
    ) PROCESS
WHERE PROCESS.INDEX_PROCESS IS NOT NULL
ORDER BY avg_fragmentation_in_percent DESC

OPEN reIndexList

FETCH NEXT
FROM reIndexList
INTO @reIndexRequest

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY

        PRINT @reIndexRequest;

        EXEC (@reIndexRequest);

    END TRY

    BEGIN CATCH
        DECLARE @ErrorMessage NVARCHAR(4000);
        DECLARE @ErrorSeverity INT;
        DECLARE @ErrorState INT;

        SELECT @ErrorMessage = 'UNABLE TO CLEAN UP INDEX WITH: ' + @reIndexRequest + ': MESSAGE GIVEN: ' + ERROR_MESSAGE()
            ,@ErrorSeverity = 9 
            ,@ErrorState = ERROR_STATE();

    END CATCH;

    FETCH NEXT
    FROM reIndexList
    INTO @reIndexRequest
END

CLOSE reIndexList;

DEALLOCATE reIndexList;

RETURN 0

GO

Ek nagevors op die web en het'n paar van die goeie artikels.By die en ek het die funksie en script hieronder wat is herorganiseer, herskep of herbou al die indekse in'n databasis.

Die eerste wat jy mag nodig wees om te lees hierdie artikel om te verstaan waarom ons nie net herskep al die indekse.

Die tweede het ons nodig het om'n funksie te bou skep script vir die indeks.So hierdie artikel kan help.Ek is ook deel van die werk funksie hieronder.

Die laaste stap in die maak van'n while lus om te vind en te organiseer al die indekse in die databasis. Hierdie video is rasper voorbeeld om dit te maak.

Funksie:

create function GetIndexCreateScript(
    @index_name nvarchar(100)
) 
returns nvarchar(max)
as
begin

declare @Return   varchar(max)

SELECT @Return = ' CREATE ' + 
    CASE WHEN I.is_unique = 1 THEN ' UNIQUE ' ELSE '' END  +  
    I.type_desc COLLATE DATABASE_DEFAULT +' INDEX ' +   
    I.name  + ' ON '  +  
    Schema_name(T.Schema_id)+'.'+T.name + ' ( ' + 
    KeyColumns + ' )  ' + 
    ISNULL(' INCLUDE ('+IncludedColumns+' ) ','') + 
    ISNULL(' WHERE  '+I.Filter_definition,'') + ' WITH ( ' + 
    CASE WHEN I.is_padded = 1 THEN ' PAD_INDEX = ON ' ELSE ' PAD_INDEX = OFF ' END + ','  + 
    'FILLFACTOR = '+CONVERT(CHAR(5),CASE WHEN I.Fill_factor = 0 THEN 100 ELSE I.Fill_factor END) + ','  + 
    -- default value 
    'SORT_IN_TEMPDB = OFF '  + ','  + 
    CASE WHEN I.ignore_dup_key = 1 THEN ' IGNORE_DUP_KEY = ON ' ELSE ' IGNORE_DUP_KEY = OFF ' END + ','  + 
    CASE WHEN ST.no_recompute = 0 THEN ' STATISTICS_NORECOMPUTE = OFF ' ELSE ' STATISTICS_NORECOMPUTE = ON ' END + ','  + 
    -- default value  
    ' DROP_EXISTING = ON '  + ','  + 
    -- default value  
    ' ONLINE = OFF '  + ','  + 
   CASE WHEN I.allow_row_locks = 1 THEN ' ALLOW_ROW_LOCKS = ON ' ELSE ' ALLOW_ROW_LOCKS = OFF ' END + ','  + 
   CASE WHEN I.allow_page_locks = 1 THEN ' ALLOW_PAGE_LOCKS = ON ' ELSE ' ALLOW_PAGE_LOCKS = OFF ' END  + ' ) ON [' + 
   DS.name + ' ] '  
FROM sys.indexes I   
 JOIN sys.tables T ON T.Object_id = I.Object_id    
 JOIN sys.sysindexes SI ON I.Object_id = SI.id AND I.index_id = SI.indid   
 JOIN (SELECT * FROM (  
    SELECT IC2.object_id , IC2.index_id ,  
        STUFF((SELECT ' , ' + C.name + CASE WHEN MAX(CONVERT(INT,IC1.is_descending_key)) = 1 THEN ' DESC ' ELSE ' ASC ' END 
    FROM sys.index_columns IC1  
    JOIN Sys.columns C   
       ON C.object_id = IC1.object_id   
       AND C.column_id = IC1.column_id   
       AND IC1.is_included_column = 0  
    WHERE IC1.object_id = IC2.object_id   
       AND IC1.index_id = IC2.index_id   
    GROUP BY IC1.object_id,C.name,index_id  
    ORDER BY MAX(IC1.key_ordinal)  
       FOR XML PATH('')), 1, 2, '') KeyColumns   
    FROM sys.index_columns IC2   
    --WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables  
    GROUP BY IC2.object_id ,IC2.index_id) tmp3 )tmp4   
  ON I.object_id = tmp4.object_id AND I.Index_id = tmp4.index_id  
 JOIN sys.stats ST ON ST.object_id = I.object_id AND ST.stats_id = I.index_id   
 JOIN sys.data_spaces DS ON I.data_space_id=DS.data_space_id   
 JOIN sys.filegroups FG ON I.data_space_id=FG.data_space_id   
 LEFT JOIN (SELECT * FROM (   
    SELECT IC2.object_id , IC2.index_id ,   
        STUFF((SELECT ' , ' + C.name  
    FROM sys.index_columns IC1   
    JOIN Sys.columns C    
       ON C.object_id = IC1.object_id    
       AND C.column_id = IC1.column_id    
       AND IC1.is_included_column = 1   
    WHERE IC1.object_id = IC2.object_id    
       AND IC1.index_id = IC2.index_id    
    GROUP BY IC1.object_id,C.name,index_id   
       FOR XML PATH('')), 1, 2, '') IncludedColumns    
   FROM sys.index_columns IC2    
   --WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables   
   GROUP BY IC2.object_id ,IC2.index_id) tmp1   
   WHERE IncludedColumns IS NOT NULL ) tmp2    
ON tmp2.object_id = I.object_id AND tmp2.index_id = I.index_id   
WHERE I.is_primary_key = 0 AND I.is_unique_constraint = 0 
AND I.[name] = @index_name

return @Return

end

Sql vir'n rukkie:

declare @RebuildIndex Table(
    IndexId int identity(1,1),
    IndexName varchar(100),
    TableSchema varchar(50),
    TableName varchar(100),
    Fragmentation decimal(18,2)
)


insert into @RebuildIndex (IndexName,TableSchema,TableName,Fragmentation)
SELECT 
    B.[name] as 'IndexName', 
    Schema_Name(O.[schema_id]) as 'TableSchema',
    OBJECT_NAME(A.[object_id]) as 'TableName',
    A.[avg_fragmentation_in_percent] Fragmentation
FROM sys.dm_db_index_physical_stats(db_id(),NULL,NULL,NULL,'LIMITED') A 
INNER JOIN sys.indexes B ON A.[object_id] = B.[object_id] and A.index_id = B.index_id  
INNER JOIN sys.objects O ON O.[object_id] = B.[object_id]  
 where B.[name] is not null and B.is_primary_key = 0 AND B.is_unique_constraint = 0 and A.[avg_fragmentation_in_percent] >= 5  

--select * from @RebuildIndex

 declare @begin int = 1
 declare @max int
 select @max = Max(IndexId) from @RebuildIndex
 declare @IndexName varchar(100), @TableSchema varchar(50), @TableName varchar(100) , @Fragmentation decimal(18,2)

 while @begin <= @max
 begin

    Select @IndexName = IndexName from @RebuildIndex where IndexId = @begin
    select @TableSchema = TableSchema  from @RebuildIndex where IndexId = @begin
    select @TableName = TableName  from @RebuildIndex where IndexId = @begin 
    select @Fragmentation = Fragmentation  from @RebuildIndex where IndexId = @begin 

    declare @sql nvarchar(max)
    if @Fragmentation < 31
    begin
        set @sql = 'ALTER INDEX ['+@IndexName+'] ON ['+@TableSchema+'].['+@TableName+'] REORGANIZE WITH ( LOB_COMPACTION = ON )'
        print 'Reorganized Index ' + @IndexName + ' for ' + @TableName + ' Fragmentation was ' + convert(nvarchar(18),@Fragmentation)
    end
    else
    begin
        set @sql = (select dbo.GetIndexCreateScript(@IndexName))
        if(@sql is not null)
        begin
            print 'Recreated Index ' + @IndexName + ' for ' + @TableName + ' Fragmentation was ' + convert(nvarchar(18),@Fragmentation)
        end 
        else
        begin
            set @sql = 'ALTER INDEX ['+@IndexName+'] ON ['+@TableSchema+'].['+@TableName+'] REBUILD PARTITION = ALL WITH (ONLINE = ON)'
            print 'Rebuilded Index ' + @IndexName + ' for ' + @TableName + ' Fragmentation was ' + convert(nvarchar(18),@Fragmentation)
        end
    end

    execute(@sql)


    set @begin = @begin+1

end
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top