meta données pour cette page
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| sql_server:database:index [23/05/2024 13:53] – mdl | sql_server:database:index [05/11/2025 09:25] (Version actuelle) – mdl | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| - | ====== | + | ====== |
| + | |||
| + | * rebuild en cours | ||
| + | <code TSQL> | ||
| + | SELECT r.session_id, | ||
| + | AS [Percent Complete], | ||
| + | CONVERT(NUMERIC(10, | ||
| + | CONVERT(NUMERIC(10, | ||
| + | CONVERT(NUMERIC(10, | ||
| + | CONVERT(VARCHAR(1000), | ||
| + | CASE WHEN r.statement_end_offset = -1 THEN 1000 ELSE (r.statement_end_offset-r.statement_start_offset)/ | ||
| + | FROM sys.dm_exec_sql_text(sql_handle))) | ||
| + | FROM sys.dm_exec_requests r WHERE command IN (' | ||
| + | </ | ||
| * Fragmentation | * Fragmentation | ||
| Ligne 19: | Ligne 32: | ||
| </ | </ | ||
| - | * Rebuild | + | |
| + | * au dessus de 30% de défragmentation => REBUILD | ||
| + | |||
| + | | ||
| <code TSQL> | <code TSQL> | ||
| --Basic Rebuild Command | --Basic Rebuild Command | ||
| ALTER INDEX Index_Name ON Table_Name REBUILD | ALTER INDEX Index_Name ON Table_Name REBUILD | ||
| - | --REBUILD Index with ONLINE OPTION (enterprise) | + | --REBUILD Index with ONLINE OPTION (enterprise |
| ALTER INDEX Index_Name ON Table_Name REBUILD WITH(ONLINE=ON) | ALTER INDEX Index_Name ON Table_Name REBUILD WITH(ONLINE=ON) | ||
| + | </ | ||
| + | |||
| + | * Reorganized (ne drop pas l' | ||
| + | <code TSQL> | ||
| + | ALTER INDEX IX_OrderTracking_SalesOrderID ON Sales.OrderTracking REORGANIZE | ||
| + | </ | ||
| + | |||
| + | |||
| + | ---- | ||
| + | |||
| + | * Script: | ||
| + | |||
| + | <code TSQL> | ||
| + | ---- | ||
| + | -- Script that reorganizes or rebuilds all indexes having an average fragmentation | ||
| + | -- percentage above a given threshold. It also works in the case | ||
| + | -- where Availability Groups are enabled as it determines if the | ||
| + | -- relevant databases are the primary replicas. | ||
| + | -- | ||
| + | -- This script supports only SQL Server 2005 or later. | ||
| + | -- Also, if you execute this script in a SQL Server 2005 instance | ||
| + | -- or later, any databases with compatibility level 2000 (80) or earlier | ||
| + | -- will be automatically excluded from the index reorganization/ | ||
| + | ---- | ||
| + | |||
| + | --Initial check - You must be SysAdmin | ||
| + | DECLARE @isSysAdmin INT | ||
| + | SET @isSysAdmin=(SELECT IS_SRVROLEMEMBER (' | ||
| + | |||
| + | --Initial check - You must be using SQL Server 2005 or later | ||
| + | DECLARE @SQLServerVersion INT | ||
| + | SET @SQLServerVersion=(SELECT CAST(LEFT(CAST(SERVERPROPERTY(' | ||
| + | |||
| + | |||
| + | IF @isSysAdmin=1 AND @SQLServerVersion >= 9 | ||
| + | BEGIN | ||
| + | |||
| + | -- | ||
| + | -- Variable/ | ||
| + | -- | ||
| + | DECLARE @dbname NVARCHAR(128); | ||
| + | DECLARE @ReorganizeOrRebuildCommand NVARCHAR(MAX); | ||
| + | DECLARE @dbid INT; | ||
| + | DECLARE @indexFillFactor VARCHAR(5); | ||
| + | DECLARE @fragmentationThreshold VARCHAR(10); | ||
| + | DECLARE @indexStatisticsScanningMode VARCHAR(20); | ||
| + | DECLARE @verboseMode BIT; | ||
| + | DECLARE @reportOnly BIT; | ||
| + | DECLARE @sortInTempdb VARCHAR(3); | ||
| + | DECLARE @isHadrEnabled BIT; | ||
| + | DECLARE @databaseToCheck VARCHAR(250) | ||
| + | DECLARE @dynamic_command NVARCHAR(1024); | ||
| + | DECLARE @dynamic_command_get_tables NVARCHAR(MAX); | ||
| + | |||
| + | --Initializations - Do not change | ||
| + | SET @databaseToCheck=NULL; | ||
| + | SET @dynamic_command = NULL; | ||
| + | SET @dynamic_command_get_tables = NULL; | ||
| + | SET @isHadrEnabled=0; | ||
| + | |||
| + | SET NOCOUNT ON; | ||
| + | |||
| + | --------------------------------------------------------- | ||
| + | --Set Parameter Values: You can change these (optional) - | ||
| + | --Note: The script has default parameters set - | ||
| + | --------------------------------------------------------- | ||
| + | --if set to 1: it will just generate a report with the index reorganization/ | ||
| + | --if set to 0: it will reorganize or rebuild the fragmented indexes | ||
| + | SET @reportOnly = 0; | ||
| + | |||
| + | --optional: if not set (NULL), it will scann all databases | ||
| + | --If name is set (i.e. ' | ||
| + | SET @databaseToCheck = NULL; | ||
| + | |||
| + | --maintains only the indexes that have average fragmentation percentage equal or higher from the given value | ||
| + | SET @fragmentationThreshold = 15; | ||
| + | |||
| + | --fill factor - the percentage of the data page to be filled up with index data | ||
| + | SET @indexFillFactor = 90; | ||
| + | |||
| + | --sets the scanning mode for index statistics | ||
| + | --available values: ' | ||
| + | SET @indexStatisticsScanningMode=' | ||
| + | |||
| + | --if set to ON: sorts intermediate index results in TempDB | ||
| + | --if set to OFF: sorts intermediate index results in user database' | ||
| + | SET @sortInTempdb=' | ||
| + | |||
| + | --if set to 0: Does not output additional information about the index reorganization/ | ||
| + | --if set to 1: Outputs additional information about the index reorganization/ | ||
| + | SET @verboseMode = 0; | ||
| + | ------------------------------ | ||
| + | --End Parameter Values Setup - | ||
| + | ------------------------------ | ||
| + | |||
| + | -- check if given database exists and if compatibility level >= SQL 2005 (90) | ||
| + | IF @verboseMode=1 | ||
| + | PRINT ' | ||
| + | |||
| + | -- if given database does not exist, raise error with severity 20 | ||
| + | -- in order to terminate script' | ||
| + | IF @databaseToCheck IS NOT NULL | ||
| + | BEGIN | ||
| + | | ||
| + | SET @checkResult=(SELECT COUNT(*) FROM master.sys.databases WHERE [name]=RTRIM(@databaseToCheck)); | ||
| + | IF @checkResult< | ||
| + | RAISERROR(' | ||
| + | |||
| + | | ||
| + | SET @checkResult=(SELECT [compatibility_level] FROM master.sys.databases WHERE [name]=RTRIM(@databaseToCheck)); | ||
| + | IF @checkResult< | ||
| + | RAISERROR(' | ||
| + | END | ||
| + | |||
| + | IF @verboseMode=1 | ||
| + | PRINT ' | ||
| + | |||
| + | -- Temporary table for storing index fragmentation details | ||
| + | IF OBJECT_ID(' | ||
| + | BEGIN | ||
| + | CREATE TABLE # | ||
| + | ( | ||
| + | [dbName] sysname, | ||
| + | [tableName] sysname, | ||
| + | | ||
| + | [indexName] sysname, | ||
| + | [databaseID] SMALLINT , | ||
| + | [objectID] INT , | ||
| + | [indexID] INT , | ||
| + | [AvgFragmentationPercentage] FLOAT, | ||
| + | | ||
| + | ); | ||
| + | END | ||
| + | |||
| + | -- Initialize temporary table | ||
| + | DELETE FROM # | ||
| + | |||
| + | -- Validate parameters/ | ||
| + | IF @sortInTempdb NOT IN (' | ||
| + | SET @sortInTempdb=' | ||
| + | |||
| + | -- Check if instance has AlwaysOn AGs enabled | ||
| + | SET @isHadrEnabled=CAST((SELECT ISNULL(SERVERPROPERTY(' | ||
| + | |||
| + | -- if database not specified scan all databases | ||
| + | IF @databaseToCheck IS NULL | ||
| + | BEGIN | ||
| + | DECLARE dbNames_cursor CURSOR | ||
| + | FOR | ||
| + | SELECT | ||
| + | s.database_id | ||
| + | FROM master.sys.databases s | ||
| + | WHERE | ||
| + | AND s.is_read_only != 1 | ||
| + | AND s.[name] NOT IN ( ' | ||
| + | AND s.[compatibility_level]> | ||
| + | ORDER BY s.database_id; | ||
| + | END | ||
| + | ELSE | ||
| + | -- if database specified, scan only that database | ||
| + | BEGIN | ||
| + | DECLARE dbNames_cursor CURSOR | ||
| + | FOR | ||
| + | SELECT | ||
| + | s.database_id | ||
| + | FROM master.sys.databases s | ||
| + | WHERE | ||
| + | AND s.is_read_only != 1 | ||
| + | AND s.[name]=RTRIM(@databaseToCheck) | ||
| + | END | ||
| + | |||
| + | -- if Always On Availability Groups are enabled, check for primary databases | ||
| + | -- (thus exclude secondary databases) | ||
| + | IF @isHadrEnabled=1 | ||
| + | BEGIN | ||
| + | |||
| + | DEALLOCATE dbNames_cursor; | ||
| + | |||
| + | -- if database not specified scan all databases | ||
| + | IF @databaseToCheck IS NULL | ||
| + | BEGIN | ||
| + | | ||
| + | FOR | ||
| + | SELECT | ||
| + | s.database_id | ||
| + | FROM master.sys.databases s | ||
| + | LEFT JOIN master.sys.dm_hadr_availability_replica_states r ON s.replica_id = r.replica_id | ||
| + | WHERE | ||
| + | AND s.is_read_only != 1 | ||
| + | AND UPPER(ISNULL(r.role_desc, | ||
| + | AND s.[name] NOT IN ( ' | ||
| + | AND s.[compatibility_level]> | ||
| + | ORDER BY s.database_id; | ||
| + | END | ||
| + | ELSE | ||
| + | -- if database specified, scan only that database | ||
| + | BEGIN | ||
| + | | ||
| + | FOR | ||
| + | SELECT | ||
| + | s.database_id | ||
| + | FROM master.sys.databases s | ||
| + | LEFT JOIN master.sys.dm_hadr_availability_replica_states r ON s.replica_id = r.replica_id | ||
| + | WHERE | ||
| + | AND s.is_read_only != 1 | ||
| + | AND UPPER(ISNULL(r.role_desc, | ||
| + | AND s.[name]=RTRIM(@databaseToCheck); | ||
| + | END | ||
| + | END | ||
| + | |||
| + | |||
| + | -- | ||
| + | -- For each database included in the cursor, | ||
| + | -- gather all tables that have indexes with | ||
| + | -- average fragmentation percentage equal or above @fragmentationThreshold | ||
| + | -- | ||
| + | OPEN dbNames_cursor; | ||
| + | FETCH NEXT FROM dbNames_cursor INTO @dbname, @dbid; | ||
| + | WHILE @@fetch_status = 0 | ||
| + | BEGIN | ||
| + | |||
| + | --If verbose mode is enabled, print logs | ||
| + | IF @verboseMode = 1 | ||
| + | BEGIN | ||
| + | PRINT '' | ||
| + | PRINT ' | ||
| + | END; | ||
| + | |||
| + | SET @dynamic_command_get_tables = N' | ||
| + | USE [' + @dbname+ N']; | ||
| + | | ||
| + | [dbName], | ||
| + | [tableName], | ||
| + | [schemaName], | ||
| + | [indexName], | ||
| + | [databaseID], | ||
| + | [objectID], | ||
| + | [indexID], | ||
| + | [AvgFragmentationPercentage], | ||
| + | [reorganizationOrRebuildCommand] | ||
| + | ) | ||
| + | SELECT | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | CASE WHEN pst.avg_fragmentation_in_percent > 30 THEN | ||
| + | '' | ||
| + | WHEN pst.avg_fragmentation_in_percent > 5 AND pst.avg_fragmentation_in_percent <= 30 THEN | ||
| + | '' | ||
| + | ELSE | ||
| + | NULL | ||
| + | END | ||
| + | FROM sys.dm_db_index_physical_stats(DB_ID(), | ||
| + | INNER JOIN sys.tables as tbl ON pst.object_id = tbl.object_id | ||
| + | INNER JOIN sys.indexes idx ON pst.object_id = idx.object_id AND pst.index_id = idx.index_id | ||
| + | WHERE pst.index_id != 0 | ||
| + | AND pst.alloc_unit_type_desc IN ( N'' | ||
| + | AND pst.avg_fragmentation_in_percent >= '+ @fragmentationThreshold + ''; | ||
| + | | ||
| + | -- if verbose | ||
| + | IF @verboseMode=1 | ||
| + | BEGIN | ||
| + | PRINT 'Index fragmentation statistics script: '; | ||
| + | PRINT @dynamic_command_get_tables; | ||
| + | END | ||
| + | |||
| + | -- gather index fragmentation statistics | ||
| + | EXEC (@dynamic_command_get_tables); | ||
| + | |||
| + | -- bring next record from the cursor | ||
| + | FETCH NEXT FROM dbNames_cursor INTO @dbname, @dbid; | ||
| + | END; | ||
| + | |||
| + | CLOSE dbNames_cursor; | ||
| + | DEALLOCATE dbNames_cursor; | ||
| + | |||
| + | ------------------------------------------------------------ | ||
| + | |||
| + | -- if ' | ||
| + | IF @reportOnly=1 | ||
| + | BEGIN | ||
| + | | ||
| + | tableName , | ||
| + | schemaName , | ||
| + | indexName , | ||
| + | AvgFragmentationPercentage , | ||
| + | reorganizationOrRebuildCommand | ||
| + | | ||
| + | ORDER BY AvgFragmentationPercentage DESC; | ||
| + | END | ||
| + | ELSE | ||
| + | -- if ' | ||
| + | -- index reorganize/ | ||
| + | BEGIN | ||
| + | | ||
| + | FOR | ||
| + | SELECT | ||
| + | FROM # | ||
| + | WHERE reorganizationOrRebuildCommand IS NOT NULL | ||
| + | ORDER BY AvgFragmentationPercentage DESC; | ||
| + | |||
| + | OPEN reorganizeOrRebuildCommands_cursor; | ||
| + | FETCH NEXT FROM reorganizeOrRebuildCommands_cursor INTO @ReorganizeOrRebuildCommand; | ||
| + | WHILE @@fetch_status = 0 | ||
| + | BEGIN | ||
| + | |||
| + | IF @verboseMode = 1 | ||
| + | BEGIN | ||
| + | PRINT '' | ||
| + | PRINT ' | ||
| + | PRINT @ReorganizeOrRebuildCommand | ||
| + | END | ||
| + | | ||
| + | EXEC (@ReorganizeOrRebuildCommand); | ||
| + | FETCH NEXT FROM reorganizeOrRebuildCommands_cursor INTO @ReorganizeOrRebuildCommand; | ||
| + | END; | ||
| + | |||
| + | CLOSE reorganizeOrRebuildCommands_cursor; | ||
| + | | ||
| + | |||
| + | PRINT '' | ||
| + | PRINT 'All fragmented indexes have been reorganized/ | ||
| + | PRINT '' | ||
| + | END | ||
| + | END | ||
| + | ELSE | ||
| + | BEGIN | ||
| + | PRINT ''; | ||
| + | PRINT ' | ||
| + | PRINT ''; | ||
| + | END | ||
| + | --End of Script | ||
| </ | </ | ||