Tài liệu SQL Server MVP Deep Dives- P13 ppt

40 358 0
Tài liệu SQL Server MVP Deep Dives- P13 ppt

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

436 CHAPTER 33 Efficient backups without indexes CREATE NONCLUSTERED INDEX ncix_Table1 ON dbo.Table1 (Col1) WITH DROP_EXISTING , ONLINE = ON ON NCIX_FG; The DROP_EXISTING option causes the newly created index to be created as the replacement of the existing index, without needing to explicitly drop the existing index (which could damage query performance for queries that might be in flight, while the index is dropped) The ONLINE option can be used to further reduce concurrency impact with SQL Server 2005 or 2008 Enterprise Edition The ON NCIX_FG clause is the main focus of our attention in this statement, which defines the new location for the nonclustered index Backing up only the PRIMARY filegroup Now that we’ve successfully separated our nonclustered indexes (one only) from the PRIMARY filegroup into a separate filegroup, it’s now possible to perform a tables-only filegroup backup Instead of issuing a standard BACKUP DATABASE command, add a filegroup specification to back up only the PRIMARY filegroup For example: BACKUP DATABASE BackupTest FILEGROUP = 'PRIMARY' TO DISK = 'E:\BackupTest_Primary.bak' SQL Server will then perform a filegroup backup of the PRIMARY filegroup only, without copying any contents from the newly created NCIX_FG to the backup set NOTE Although no data is backed up from NCIX_FG, the backup still contains definitions of nonclustered indexes because index metadata information is stored in system tables, which are located in the PRIMARY filegroup (sys.indexes, sys.index_columns and so on) This means that we can recreate the nonclustered indexes in the restore process from their definitions, even though we don’t have their allocated data structures in our backup file Restoring the PRIMARY filegroup backup The process required to restore the database from the PRIMARY filegroup backup differs depending on whether you’re restoring only to perform data extraction purposes (re-creation of indexes not required), or whether you intend to bring the database fully online (re-creation of indexes is required) Restoring from the PRIMARY filegroup backup to perform data extraction is simple and faster than restoring a full backup On the other hand, restoring the database back to its full state to bring it back into a production role—including a rebuild of all nonclustered indexes—requires more steps than from a simple full database backup Let’s quickly review both of the steps required in each scenario Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross Restoring the PRIMARY filegroup backup 437 Restoring for extraction only When restoring a database from the PRIMARY (tables-only) filegroup for data extraction/examination only, you include FILEGROUP and RECOVERY (or NORECOVERY if you also wish to restore a chain of log backups) clauses in your RESTORE command, as follows: RESTORE DATABASE BackupTest FILEGROUP = 'PRIMARY' FROM DISK = 'E:\BackupTest_Primary.bak' WITH RECOVERY SQL Server will then restore the PRIMARY filegroup and recover the database, bring- ing it online and available for querying This allows extraction of data by executing SELECT commands, but INSERT, UPDATE, or DELETE commands will fail with error 8607: Msg 8607, Level 16, State 1, Line 1: The table '[Tablename]' cannot be modified because one or more nonclustered indexes reside in a filegroup which is not online It’s also possible that SELECT statements might fail if a nonclustered index is used to process the query, either via selection by SQL Server’s query optimizer or explicit index hint In this case, error 315 will be returned: Msg 315, Level 16, State 1, Line 2: Index "[IndexName]" on table "[TableName]" (specified in the FROM clause) is disabled or resides in a filegroup which is not online In this scenario, you might need to either remove index hints, or explicitly hint SQL Server to access the table via its heap or clustered index storage, instead of via the nonclustered index (which is offline) Restoring for production use Restoring a database from a PRIMARY filegroup backup for production use does require a few more steps than restoring from a regular full database backup The most significant of these involves rebuilding nonclustered indexes from the underlying tables In summary, these are the steps required to bring a database fully online from a PRIMARY filegroup backup: Restore the primary filegroup backup and recover the database Script out index definitions from the PRIMARY filegroup, using a new filegroup name Restart SQL Server in single-user mode (with -m startup parameter) Connect to SQL Server using the Dedicated Administrator Connection Delete nonclustered index definitions from the sys.sysindexes system view Remove -m startup parameter and restart SQL Server in multi-user mode Create a new, renamed filegroup to re-create the nonclustered indexes in Rebuild nonclustered indexes in the new filegroup Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross 438 CHAPTER 33 NOTE Efficient backups without indexes Scripting nonclustered index definitions from the PRIMARY filegroup is still possible even though the nonclustered index filegroup hasn’t been restored, because index definitions exist within the system meta tables in the PRIMARY filegroup, regardless of where the physical index storage allocations are located This is a crucial fact that enables this technique to work Before walking through each of these steps, two issues associated with this technique should be discussed: ƒ An update to system views is required to re-create nonclustered indexes (step 5) ƒ The nonclustered index filegroup’s name must be changed (step 7) ISSUE 1: INDEX DEFINITIONS MUST BE REMOVED BY UPDATING A SYSTEM VIEW The process of re-creating indexes following restoration of the PRIMARY filegroup requires deleting existing index metadata from the sys.sysindexes system view prior to re-creating indexes (step in the previous list) This fact might discourage some from using this technique, but it should be pointed out that updating this system view does not, in and of itself, compromise the integrity of the database, as the database tables that contain the real data in our database are stored within the PRIMARY filegroup and are not affected by the update of this system view WARNING Updating a system catalog is an operation that’s not supported by Microsoft An alternative supported solution is to reconstruct the database by scripting its definition, re-creating the database, exporting all table data from the backup, and re-importing to the new re-created database This system update is required because neither DROP INDEX nor CREATE INDEX WITH DROP_EXISTING work when only the PRIMARY filegroup has been restored Each fails with an error stating that the index’s filegroup is offline as SQL Server attempts to remove the index’s allocations, which aren’t available during execution of the command To avoid this system catalog update, an alternative is to re-create an entirely new database by scripting all database objects from the PRIMARY filegroup (tables, indexes, and all other objects) and exporting all data from the restored PRIMARY filegroup into that new database This is obviously more time-consuming than only recreating nonclustered indexes (as tables are also re-created in the new database), but it’s a workable alternative that allows you to bring a database back online from PRIMARY filegroup backup without using any system catalog updates ISSUE 2: NEW NONCLUSTERED INDEX FILEGROUP MUST BE RENAMED Another issue is that the filegroup that contained the nonclustered indexes in the source database (NCIX_FG in our example) cannot be fully removed from the restored database without further system catalog updates This is less of a problem though, as another filegroup can be added to the restored database and nonclustered indexes be built into it The name of a filegroup Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross Restoring the PRIMARY filegroup backup 439 is rarely important to an application, so this doesn’t pose a serious problem—simply create another filegroup (for example NCIX_FG2) and rebuild nonclustered indexes into it instead This is what we’ll in our example Restoring for production use—step by step Let’s walk through the individual steps required to restore our database for production use from a PRIMARY filegroup backup STEP 1—RESTORE THE PRIMARY FILEGROUP BACKUP AND RECOVER THE DATABASE The first step is identical to the restore process for extraction only Assuming our PRIMARY filegroup backup remains located in the root of E:\ drive, execute the following command: RESTORE DATABASE BackupTest FILEGROUP = 'PRIMARY' FROM DISK = 'E:\BackupTest_Primary.bak' WITH RECOVERY This restores the database’s PRIMARY filegroup, meaning that all tables, views, stored procedures, user-defined functions, and other database objects stored in the PRIMARY filegroup have been restored to the database Index definitions have also been restored to the system catalogs (which reside in the PRIMARY filegroup), but their data structure allocations have not, as they are located within the dedicated nonclustered index filegroup (NCIX_FG in our example)—which was neither backed up nor restored STEP 2—SCRIPT OUT INDEX DEFINITIONS FROM PRIMARY FILEGROUP In the current state of our database, it’s not possible to rebuild our nonclustered indexes using more convenient options such as DBCC DBREINDEX, ALTER INDEX REBUILD, or CREATE INDEX WITH DROP_EXISTING Each of these generates an error whether executed from a normal connection or dedicated administrator connection (DAC), because each requires existing index allocations to be available during execution of the command Instead, we’ll script index definitions out to a file and use the script later (step 8), to rebuild the indexes, after we have dropped index definitions from the sys.sysindexes system catalog and created a new nonclustered index filegroup to contain the new indexes To generate the index scripts, use the utility stored procedure (SP) described later in this chapter, named usp_Manage_NCIX_FileGroup This SP accepts two parameters—@ScriptOnlyOrExecute (nvarchar(6)) and @NCIXFGName (nvarchar(255)) The @ScriptOnlyOrExecute parameter should be set to N'Script', which instructs the SP to generate scripts only, without executing them The @NCIXFGName parameter should be provided with the name of a new filegroup to rebuild nonclustered indexes into At this stage, this filegroup does not exist, but we’ll create it in step The name provided for this new filegroup must be different from the existing nonclustered index filegroup for this database (which is Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross 440 CHAPTER 33 Efficient backups without indexes NCIX_FG in our example) because that filegroup’s descriptive metadata still exists in the system catalogs For our example, we’ll create another filegroup named N'NCIX_FG2' EXEC usp_Manage_NCIX_FileGroup N'Script', N'NCIX_FG2' Output from the execution of this procedure should contain a list of CREATE INDEX statements, one per nonclustered index in the database Save this output to a script file (for example NCIXScripts.sql) for later use in step Note that each CREATE INDEX statement will include the filegroup name NCIX_FG2 When we run this script later, nonclustered indexes will be re-created within this filegroup, so we’ll need to add it to the database (which we in step 7) STEP 3—RESTART SQL SERVER IN SINGLE-USER MODE Before we can re-create our nonclustered indexes, we need to remove existing index definitions from the database by deleting them from the sys.sysindexes system catalog This requires us to connect to SQL Server in single-user mode, using the DAC before we can perform the DELETE Starting SQL Server in single-user mode requires adding the -m startup parameter via the SQL Server 2005 or 2008 Configuration Manager utility, as displayed in figure 4 Navigate to the SQL Server Program Files menu Open the SQL Server Configuration Manager utility Right-click on the relevant instance of SQL Server from the right-hand window Select the Properties menu Click on the Advanced tab Select the Startup Parameters configuration Add ; -m to the end of the existing list of Startup Parameters (or the beginning of Startup Parameters with SQL Server 2008) Click Apply, and click OK in the warning dialog box that appears Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross Restoring the PRIMARY filegroup backup 441 When the Properties dialog box closes, right-click on the SQL Server instance and select Restart Figure Adding the -m startup parameter in SQL Server Configuration Manager STEP 4—CONNECT TO SQL SERVER USING DEDICATED ADMINISTRATOR CONNECTION Once the SQL Server instance has been restarted, connect through the DAC to allow updates to the system catalogs Connect or reconnect an SSMS connection by adding ADMIN: to the beginning of the server name in your connection dialog box, as displayed in figure Figure Specifying the Dedicated Administrator Connection using the SSMS connection dialog box STEP 5—DELETE NONCLUSTERED INDEX DEFINITIONS Once connected through the DAC, delete existing nonclustered index definitions from the system schema by running the following command: DELETE FROM sys.sysindexes WHERE OBJECTPROPERTY (id, 'IsUserTable') = AND indid > AND indid < 255 Executing this command allows us to run the script generated in step to re-create all nonclustered indexes—but first we need to remove the -m startup parameter, restart Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross 442 CHAPTER 33 Efficient backups without indexes the SQL Server, and add a new nonclustered index using the filegroup name specified for the @NCIXFGName parameter in step STEP 6—REMOVE -M STARTUP PARAMETER AND RESTART SQL SERVER To remove the -m startup parameter, follow the steps outlined in step but remove ; -m from the Startup Parameters configuration before restarting the SQL Server instance STEP 7—CREATE A NEW, RENAMED FILEGROUP Once the SQL Server instance has been restarted in multi-user (normal) mode, a new filegroup must be added prior to re-creating the database’s nonclustered indexes This is a two-step process; first we create the filegroup by executing the following command: ALTER DATABASE BackupTest ADD FILEGROUP NCIX_FG2; Then, we add at least one file to the filegroup by executing the following command: ALTER DATABASE BackupTest ADD FILE ( NAME = N'NCIX_FG2_F1' , FILENAME = N'C:\ NCIX_FG2_F1.ndf') TO FILEGROUP NCIX_FG2; NOTE The name used for this new filegroup must match the name provided to the parameter @NCIXFGName in step because the script generated in step will attempt to build nonclustered indexes into this filegroup when it is run in step STEP 8—REBUILD NONCLUSTERED INDEXES IN THE NEW FILEGROUP To re-create the nonclustered indexes in the new filegroup, connect to the database using SSMS and execute the script created in step usp_Manage_NCIX_Filegroup This utility stored procedure has been designed to simplify two tasks described in this technique: ƒ Move a large number of nonclustered indexes into a dedicated filegroup, as part of reorganizing your database in preparation to perform PRIMARY (tablesonly) filegroup-based backups ƒ Generate a script to re-create nonclustered indexes during the restore process if necessary The workflow of this stored procedure iterates over a database’s indexes, generating a CREATE INDEX statement for each index, and either executes the statement (when reorganizing the database in preparation for performing PRIMARY filegroup backups) or prints the statement (to generate scripts for re-creating nonclustered indexes during restore) The value supplied for the @ScriptOnlyOrExecute parameter defines which behavior will occur Supply N'Execute' to execute the scripts (moving the Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross usp_Manage_NCIX_Filegroup 443 indexes into the filegroup named in the other parameter @NCIXFGName) or N'Script' to script out the CREATE INDEX statements when restoring the database Note that slightly different CREATE INDEX statements are generated when N'Execute' is supplied to the @ScriptOnlyOrExecute parameter When N'Execute' is supplied, WITH DROP_EXISTING is appended to the CREATE INDEX statement so that each existing index remains in place while a new copy is being created in the new, dedicated nonclustered index filegroup In addition, the script identifies whether the edition of the SQL Server instance is Enterprise or Standard Edition and includes WITH ONLINE=ON if Enterprise Edition is detected The idea here is to cause minimal interruption to queries during reorganization of the database, with close to zero interruption if the Enterprise Edition of SQL Server is in use Here’s a sample usage Move all nonclustered indexes into a newly created filegroup named 'NCIX_FG': EXEC usp_Manage_NCIX_FileGroup N'Exec', N'NCIX_FG' As in listing 1, script out CREATE INDEX statements into a newly created filegroup named 'NCIX_FG2' Listing Scripting CREATE INDEX commands to a new filegroup EXEC usp_Manage_NCIX_FileGroup N'Script', N'NCIX_FG2' CREATE PROCEDURE [dbo].[usp_Manage_NCIX_FileGroup] @ScriptOnlyOrExecute NVARCHAR(6) /* N'Script' or N'Exec' */ , @NCIXFGName NVARCHAR(255) /* the name new filegroup to move NCIXs into*/ AS SET NOCOUNT ON /*cursor variables*/ DECLARE @tnm NVARCHAR(128), @ixnm NVARCHAR(128), @cnm NVARCHAR(128) , @schnm NVARCHAR(128), @isPK BIT, @isUn BIT, @isIncCol BIT , @cixnm NVARCHAR(128), @ctbschnm NVARCHAR(256) , @ixcr NVARCHAR(4000), @ixcnt INT, @indid INT, @order NVARCHAR(5) , @inccols NVARCHAR(4000) SELECT @ixcnt = 0, @cixnm = N'', @ctbschnm = N'' /*open cursor over schema / table / index / columns*/ DECLARE cr CURSOR FOR SELECT ss.name, so.name, si.name, N'[' + sc.name + N']', is_primary_key , CASE WHEN is_descending_key = THEN N'' ELSE N' DESC' END , is_included_column, si.index_id, is_unique FROM sys.schemas ss JOIN sys.objects so on ss.schema_id = so.schema_id JOIN sys.indexes si on so.object_id = si.object_id JOIN sys.index_columns ic ON si.object_id = ic.object_id AND si.index_id = ic.index_id JOIN sys.columns sc ON ic.object_id = sc.object_id AND ic.column_id = sc.column_id WHERE OBJECTPROPERTY (so.object_id, 'IsUserTable') = AND si.index_id > AND si.index_id < 255 /*only interested in NCIXs*/ ORDER BY ss.name, so.name, si.name, ic.index_column_id /*order crucial for cursor logic*/ Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross 444 CHAPTER 33 Efficient backups without indexes OPEN cr FETCH NEXT FROM cr INTO @schnm, @tnm, @ixnm, @cnm, @isPK, @order, @isIncCol, @indid, @isUn /*move over cursor, constructing & executing a drop / create index statement per index*/ WHILE @@FETCH_STATUS = BEGIN IF @ixnm != @cixnm or (@schnm+@tnm != @ctbschnm) /*new index or table*/ BEGIN /*if index, table or schema name changes, reinitialise*/ IF @schnm+@tnm != @ctbschnm SET @ctbschnm = @schnm+@tnm SELECT @ixcnt = @ixcnt + IF @ixcnt > BEGIN SELECT @ixcr = LEFT(@ixcr, LEN(@ixcr) - 2) + N')' + CASE WHEN LEN(@inccols) > THEN N' INCLUDE (' + LEFT(@inccols, LEN(@inccols) - 2) + N')' ELSE N'' END + N' WITH (DROP_EXISTING = ON' + CASE WHEN SERVERPROPERTY('EngineEdition') = THEN N', ONLINE = ON)' ELSE N')' END + N' ON [' + @NCIXFGName + ']' /*execution of create NCIX in other FG occurs on first row of NEXT index*/ PRINT @ixcr; IF @ScriptOnlyOrExecute = N'Exec' EXEC(@ixcr) END SELECT @cixnm = @ixnm, @inccols = '' SET @ixcr = N'create ' + CASE WHEN @isUn = THEN N'unique ' ELSE N'' END + N'nonclustered index [' + @ixnm + N'] on [' + @schnm + N'].[' + @tnm + N'] (' + @cnm + @order + N', ' END ELSE BEGIN /*if same index, build key of included cols csv list*/ IF @isIncCol != SET @inccols = @inccols + @cnm + N', ' ELSE SET @ixcr = @ixcr + @cnm + @order + N', ' END FETCH NEXT FROM cr INTO @schnm, @tnm, @ixnm, @cnm, @isPK, @order, @isIncCol, @indid, @isUn END /*should usually be one last index (assuming there were any)*/ IF @ixcnt > BEGIN SELECT @ixcr = LEFT(@ixcr, LEN(@ixcr) - 2) + N')' + CASE WHEN LEN(@inccols) > THEN N' INCLUDE (' + LEFT(@inccols, LEN(@inccols) - 2) + N')' ELSE N'' END + N' WITH (DROP_EXISTING = ON' + CASE WHEN SERVERPROPERTY('EngineEdition') = THEN N', ONLINE = ON)' ELSE N')' END + N' ON [' + @NCIXFGName + ']' Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross Planning before moving NCIXs into a dedicated filegroup 445 PRINT @ixcr; IF @ScriptOnlyOrExecute = N'Exec' EXEC(@ixcr) END CLOSE cr ; DEALLOCATE cr Note the following points about the preceding script: ƒ The script iterates over all schemas and their user tables within the current database, identifying all nonclustered indexes and generating a CREATE INDEX WITH DROP_EXISTING ON [NCIX_FG] script for each index, which is then executed dynamically to move each nonclustered index ƒ The script will not attempt to move tables Heaps or clustered indexes are eliminated by the cursor query’s WHERE filter: and si.index_id > and si.index_id < 255" ƒ Unique definitions, key order, and included columns are all also preserved, so nonclustered indexes should be moved identically with their current definitions ƒ Each individual CREATE INDEX statement is also printed, allowing easy review of the commands that have been dynamically executed by the script Planning before moving NCIXs into a dedicated filegroup Using the usp_Manage_NCIX_FileGroup utility stored procedure makes moving all of your database’s nonclustered indexes into a new, dedicated nonclustered index filegroup an easy process, but there are some important considerations that need to be addressed before doing this Moving NCIXs temporarily requires additional disk space As nonclustered indexes are moved into the new, dedicated nonclustered index filegroup, extra space needs to be consumed in the filesystem by the filegroup to allocate new page extents to contain the moved nonclustered indexes At the same time, space is being freed within the PRIMARY filegroup (as each nonclustered index is moved out to the new filegroup) but this space is not freed back to the filesystem Filegroup space is only returned to the filesystem if the filegroup’s files are explicitly shrunk, using DBCC SHRINKFILE This doesn’t happen automatically, so moving nonclustered indexes out of the PRIMARY filegroup to a new dedicated nonclustered index filegroup will require consumption of more filesystem space How much more space is required depends on how much nonclustered index data your database contains The more nonclustered index data you have, the more filesystem space you need for the new filegroup but the more space you will save in your tables-only filegroup backups The amount of space consumed by nonclustered indexes can be roughly estimated in SQL Server 2005 and SQL Server 2008 by running the following query: SELECT SUM(page_count) * 8192.0 / 1048576 as NCIXs_Mb FROM sys.dm_db_index_physical_stats(db_id(), NULL, NULL, NULL , 'LIMITED') Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Licensed to Kerri Ross ... mirroring? SQL Server 2005 introduced database mirroring, and SQL Server 2008 enhanced it Back in the pre -SQL Server 2005 days, you had several choices for high availability solutions with SQL Server, ... receive Microsoft’s SQL Server MVP award in 2003 He has gained significant expertise in SQL Server tuning, and most of his professional time is currently spent tuning customer SQL Server systems Greg... dedicated SQL Server support business—and also Australian Director of SQLskills, a specialist provider of SQL Server training Greg has worked in a range of developer and DBA capacities with SQL Server

Ngày đăng: 15/12/2013, 13:15

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan