Tải bản đầy đủ - 0 (trang)
14-6. Storing Metadata, and Then Scripting and Executing DROP and CREATE Statements for Destination Database XML Indexes

14-6. Storing Metadata, and Then Scripting and Executing DROP and CREATE Statements for Destination Database XML Indexes

Tải bản đầy đủ - 0trang

Chapter 14 ■ ETL Process Acceleration



,PrimaryIndexName

,XMLPrimaryIndexID

,DataSpace

,TableID

,[Allow_Page_Locks]

,[Allow_Row_Locks]

,Is_Padded

,IsPrimaryXMLIndex

,XMLColumnName

)



SELECT

@SERVER_NAME

,@DATABASE_NAME

,SCH.name AS SCHEMA_NAME

,TBL.name AS TABLE_NAME

,XIN.name AS INDEX_NAME

,XIN.index_id AS IndexID

,DSP.name AS DataSpace

,TBL.object_id AS TableID

,XIN.allow_page_locks

,XIN.allow_row_locks

,XIN.is_padded

,1

,COL.name



FROM

sys.tables TBL

INNER JOIN sys.xml_indexes XIN

ON TBL.object_id = XIN.object_id

INNER JOIN sys.schemas SCH

ON TBL.schema_id = SCH.schema_id

INNER JOIN sys.data_spaces DSP

ON XIN.data_space_id = DSP.data_space_id

INNER JOIN sys.index_columns SIC

ON XIN.index_id = SIC.index_id

AND XIN.object_id = SIC.object_id

INNER JOIN sys.columns COL

ON SIC.object_id = COL.object_id

AND SIC.column_id = COL.column_id



WHERE

XIN.secondary_type_desc IS NULL ;



-- Secondary XML indexes



INSERT INTO #Metadata_XMLIndexes

(

SERVER_NAME

,DATABASE_NAME

,SCHEMA_NAME

,TABLE_NAME

,PrimaryIndexName



829

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



,TableID

,XMLPrimaryIndexID

,XMLSecondaryaryIndexID

,INDEX_NAME

,SecondaryTypeDescription

,DataSpace

,Allow_Page_Locks

,Allow_Row_Locks

,Is_Padded

,IsPrimaryXMLIndex

,XMLColumnName

)





SELECT

@SERVER_NAME AS SERVER_NAME

,@DATABASE_NAME AS DATABASE_NAME

,SCH.name AS SCHEMA_NAME

,TBL.name AS TABLE_NAME

,SIX.name AS PrimaryIndexName

,TBL.object_id AS TableID

,SIX.index_id AS XMLPrimaryIndexID

,XIN.index_id AS XMLSecondaryaryIndexID

,XIN.name AS INDEX_NAME

,XIN.secondary_type_desc AS SecondaryTypeDescription

,DSP.name AS DataSpace

,XIN.allow_page_locks AS AllowPageLocks

,XIN.allow_row_locks AS AllowRowLocks

,XIN.is_padded AS IsPadded

,0

,COL.name



FROM

sys.indexes SIX

INNER JOIN sys.tables TBL

ON SIX.object_id = TBL.object_id

INNER JOIN sys.xml_indexes XIN

ON SIX.object_id = XIN.object_id

AND SIX.index_id = XIN.using_xml_index_id

INNER JOIN sys.schemas SCH

ON TBL.schema_id = SCH.schema_id

INNER JOIN sys.data_spaces DSP

ON XIN.data_space_id = DSP.data_space_id

INNER JOIN sys.index_columns SIC

ON XIN.index_id = SIC.index_id

AND XIN.object_id = SIC.object_id

INNER JOIN sys.columns COL

ON SIC.object_id = COL.object_id

AND SIC.column_id = COL.column_id

;



830

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



3.



Execute the following code to DROP XML indexes in the selected database

(C:\SQL2012DIRecipes\CH14\DropXMLIndexes.Sql):

-- Drop table to hold script elements



IF OBJECT_ID('tempdb..#ScriptElements') IS NOT NULL

DROP TABLE tempdb..#ScriptElements;



CREATE TABLE #ScriptElements (ID INT IDENTITY(1,1), ScriptElement NVARCHAR(MAX))



-- Non-Clustered Indexes



IF OBJECT_ID('tempdb..#Tmp_IndexedFields') IS NOT NULL

DROP TABLE tempdb..#Tmp_IndexedFields;



-- Secondary XML index



INSERT INTO #ScriptElements



SELECT DISTINCT

'DROP INDEX '

+ INDEX_NAME

+ ' ON '

+ DATABASE_NAME + '.' + SCHEMA_NAME + '.' + TABLE_NAME



FROM

Metadata_XMLIndexes



WHERE

IsPrimaryXMLIndex = 0 ;



-- Primary XML index



INSERT INTO #ScriptElements



SELECT DISTINCT

'DROP INDEX '

+ PrimaryIndexName

+ ' ON '

+ DATABASE_NAME + '.' + SCHEMA_NAME + '.' + TABLE_NAME



FROM

Metadata_XMLIndexes



WHERE

IsPrimaryXMLIndex = 1 ;



-- Drop and execute DROP scripts



DECLARE

@DropIndex NVARCHAR(MAX)



DECLARE

DropIndex_CUR CURSOR



FOR

SELECT ScriptElement FROM #ScriptElements ORDER BY ID





831

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



OPEN DropIndex_CUR



FETCH NEXT FROM DropIndex_CUR INTO @DropIndex



WHILE @@FETCH_STATUS <> −1

BEGIN



EXEC (@DropIndex)



FETCH NEXT FROM DropIndex_CUR INTO @DropIndex



END ;



CLOSE DropIndex_CUR;

DEALLOCATE DropIndex_CUR;

4.



Now you can run your ETL package that loads the source data into the

destination—or staging—database.



5.



Run the following T-SQL to re-create XML indexes in the staging database

(C:\SQL2012DIRecipes\CH14\CreateXMLIndexes.Sql):

DECLARE @SORT_IN_TEMPDB BIT = 1

DECLARE @DROP_EXISTING BIT = 0



-- Create table to hold script elements



IF OBJECT_ID('tempdb..#ScriptElements') IS NOT NULL

DROP TABLE tempdb..#ScriptElements;



CREATE TABLE #ScriptElements (ID INT IDENTITY(1,1), ScriptElement NVARCHAR(MAX))



-- Non-Clustered Indexes



IF OBJECT_ID('tempdb..#Tmp_IndexedFields') IS NOT NULL

DROP TABLE tempdb..#Tmp_IndexedFields;



INSERT INTO #ScriptElements



SELECT DISTINCT

'CREATE PRIMARY XML INDEX '

+ PrimaryIndexName

+ ' ON '

+ DATABASE_NAME + '.' + SCHEMA_NAME + '.' + TABLE_NAME

+ ' (' + XMLColumnName + ') '

+ ' WITH ('

+ CASE

WHEN is_padded = 1 THEN ' PAD_INDEX = OFF, '

ELSE ' PAD_INDEX = ON, '

END



832

www.it-ebooks.info



Chapter 14 ■ etL proCess aCCeLeration



+ CASE

WHEN [allow_page_locks] = 1 THEN ' ALLOW_PAGE_LOCKS = ON, '

ELSE 'ALLOW_PAGE_LOCKS = OFF, '

END

+ CASE

WHEN [allow_row_locks] = 1 THEN ' ALLOW_ROW_LOCKS = ON, '

ELSE ' ALLOW_ROW_LOCKS = OFF, '

END

+ CASE

WHEN @SORT_IN_TEMPDB = 1 THEN ' SORT_IN_TEMPDB = ON, '

ELSE ' SORT_IN_TEMPDB = OFF, '

END

+ CASE

WHEN @DROP_EXISTING = 1 THEN ' DROP_EXISTING = ON, '

ELSE ' DROP_EXISTING = OFF '

END

+ ')'

FROMMetadata_XMLIndexes

WHEREIsPrimaryXMLIndex = 1 ;

-- Secondary XML index

INSERT INTO #ScriptElements

SELECT

'CREATE XML INDEX '

+ INDEX_NAME

+ ' ON '

+ DATABASE_NAME + '.' + SCHEMA_NAME + '.' + TABLE_NAME

+ ' (' + XMLColumnName + ') '

+ ' USING XML INDEX '

+ PrimaryIndexName

+ ' FOR ' + secondarytypedescription

+ ' WITH ('

+ CASE

WHEN is_padded = 1 THEN ' PAD_INDEX = OFF, '

ELSE ' PAD_INDEX = ON, '

END

+ CASE

WHEN [allow_page_locks] = 1 THEN ' ALLOW_PAGE_LOCKS = ON, '

ELSE 'ALLOW_PAGE_LOCKS = OFF, '

END

+ CASE

WHEN [allow_row_locks] = 1 THEN ' ALLOW_ROW_LOCKS = ON, '

ELSE ' ALLOW_ROW_LOCKS = OFF, '

END

+ CASE

WHEN @SORT_IN_TEMPDB = 1 THEN ' SORT_IN_TEMPDB = ON, '

ELSE ' SORT_IN_TEMPDB = OFF, '

END



833

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



+ CASE

WHEN @DROP_EXISTING = 1 THEN ' DROP_EXISTING = ON, '

ELSE ' DROP_EXISTING = OFF '

END

+ ')'



FROM

Metadata_XMLIndexes

WHERE

IsPrimaryXMLIndex = 0

ORDER BY SERVER_NAME, DATABASE_NAME, SCHEMA_NAME, TABLE_NAME ;



-- Create and execute CREATE scripts



DECLARE @CreateIndex NVARCHAR(MAX)



DECLARE CreateIndex_CUR CURSOR



FOR

SELECT ScriptElement FROM #ScriptElements ORDER BY ID



OPEN CreateIndex_CUR



FETCH NEXT FROM CreateIndex_CUR INTO @CreateIndex



WHILE @@FETCH_STATUS <> −1

BEGIN



EXEC (@CreateIndex)



FETCH NEXT FROM CreateIndex_CUR INTO @CreateIndex



END ;



CLOSE CreateIndex_CUR;

DEALLOCATE CreateIndex_CUR;



How It Works

This recipe is rather like the sum of Recipes 14-3, 14-4, and 14-5—but with all the parts of the process rolled into

one. It does the following (and it will only work if you already generated the “core” index metadata—specifically

the primary key):





First, it stores the metadata required to DROP and CREATE XML indexes in the table

Metadata_XMLIndexes.







Second, it uses this information to generate and execute DROP scripts.







Finally, it uses this information to generate and execute CREATE scripts.



These scripts can be placed in an ETL process at appropriate stages in the process, as demonstrated in Recipe 14-2.

The fields created by the script are described in Table 14-3.



834

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



Table 14-3.  Fields Used to Store XML Index Metadata



Field Name



Source Table



Description



SERVER_NAME



Gets the server name from the current environment.



DATABASE_NAME



Gets the database name from the current environment.



SCHEMA_NAME



sys.schemas



The schema name.



TABLE_NAME



sys.tables



The table name.



PrimaryIndexName



sys.indexes



The index name for the primary key.



TableID



sys.tables



The internal table id in the system tables.



INDEX_NAME



sys.xml_indexes



The primary XML index name.



XMLSecondaryaryIndexID



sys.xml_indexes



The secondary XML index internal ID.



XMLPrimaryIndexID



sys.xml_indexes



The primary XML index internal ID.



SecondaryTypeDescription



sys.xml_indexes



The type of secondary index.



DataSpace



sys.dataspaces



The index storage.



Allow_Page_Locks



sys.xml_indexes



Are page locks allowed?



Allow_Row_Locks



sys.xml_indexes



Are row locks allowed?



Is_Padded



sys.xml_indexes



Are the indexes padded?



IsPrimaryXMLIndex



sys.xml_indexes



Is this the primary XML index.



XMLColumnName



sys.xml_indexes



The name of the column in the table storing XML data.



■■Note  You cannot re-create XML indexes unless the table’s primary key has been created first.



Hints, Tips, and Traps





The scripts used to store the XML index metadataDROP and subsequently CREATE the

indexes can be turned into stored procedures and called from SSIS Execute SQL tasks in

an SSIS package.







The XML index metadata can be stored in a separate database or a separate schema, if

you prefer.



14-7. Finding Missing Indexes

Problem

You suspect that indexes are missing in your destination database and want to deduce and create them.



835

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



Solution

Use the missing index DMVs. This requires you to run the following T-SQL snippet:

SELECT

TOP (100) PERCENT

sys.objects.name AS TableName

,COALESCE(sys.dm_db_missing_index_details.equality_columns

,sys.dm_db_missing_index_details.inequality_columns) AS IndexCols

,sys.dm_db_missing_index_details.included_columns

,user_seeks

,user_scans



FROM

sys.dm_db_missing_index_details

INNER JOIN sys.objects

ON sys.dm_db_missing_index_details.object_id = sys.objects.object_id

INNER JOIN sys.dm_db_missing_index_groups

ON sys.dm_db_missing_index_details.index_handle =

sys.dm_db_missing_index_groups.index_handle

INNER JOIN sys.dm_db_missing_index_group_stats

ON sys.dm_db_missing_index_groups.index_group_handle =

sys.dm_db_missing_index_group_stats.group_handle

ORDER BY

TableName, IndexCols ;



How It Works

Use SQL Server’s Missing Index DMVs to determine if there are any missing indexes—and if these indexes are

useful. The Missing Index DMVs will not only give you the core columns and tables that you can use to script

out any necessary CREATE INDEX statements, but also give you an indication (in the user_seeks and user_scans

columns) of the number of times an index is used by your process. An index that is used only once might not be

worth creating. If it is used more than once, then it should probably be given serious consideration.

My advice here is—assuming that you are running an ETL process on a development server with no one but

you connected—is to restart the SQL Server instance, and then run your ETL process from end to end. That way,

only you (the developer) can decide whether an index needs to be used in an ETL process. SQL Server has many

tools to suggest indexes; you can decide whether to apply them or not.

I will not attempt any exhaustive description of indexing requirements here—there are so many thousands

of pages published on paper and on the Web that this is not necessary. So I hope that a succinct overview from an

ETL perspective will suffice.

Should you wish to get SQL Server’s opinion on any missing indexes for a particular query, then using the

STATISTICS XML option is often the fastest and simplest route. All you have to do is encase your query in SET

STATISTICS XML ON and SET STATISTICS XML OFF like this:

SET STATISTICS XML ON



SELECT ...

FROM ...

WHERE ...



SET STATISTICS XML OFF

GO



836

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



You will then see (if there are potentially missing indexes) an XML snippet at the top of the XML showplan,

which indicates any missing indexes. This is not particularly hard to read; for each table, any equality, inequality,

and included columns are indicated. You can “nest” a series of SQL statements, or even lists of stored procedures,

between the SHOWPLAN statements, and get a series of XML results that you can then analyze independently.

Another way to see potentially missing indexes—and as well, the script to create the indexes—is to display

the actual or estimated execution plan in SSMS/SSDT. In addition to the execution plan, you get (in a fetching

shade of green) the missing index(es). Right-clicking the missing index gives you the Missing Index Details...

option. Clicking it scripts out the CREATE INDEX statement.

You need to be aware that SSMS/SSDT will not output an execution plan and the XML showplan, if you ask

for both. Moreover, apart from the toolbar buttons, you can also use Query/Display Estimated Execution Plan

and Include Actual Execution Plan to display execution plans. When all is said and done, this is the same output

as entering the SHOWPLAN statements.

If you prefer a more robust approach to tuning your queries, then you may prefer to use the Database Tuning

Advisor. This gives more information than you could need, but most of it is useful—the estimated query size, for

example. To use the Database Tuning Advisor, perform the following steps.

1.



Right-click and select Analyze Query in Database Tuning Advisor.



2.



Connect to the Database Tuning Advisor. Query should be selected in the General tab.



3.



Select the database that you will use for the query.



4.



Click Start Analysis in the toolbar.



5.



In the Recommendations tab, right-click in the Definition column for every

suggestion where the Target of Recommendation column contains the word “Index”

to get a CREATE INDEX script.



Hints, Tips, and Traps





Remember—once again—that you do not have to use the indexes that are suggested.







As the multiple options of the Database Tuning Advisor are explained in detail in Books

Online and in many excellent articles on the Web, I will not go through them here.



14-8. Managing Check Constraints

Problem

You want to drop check constraints before loading data and re-enable them after the data load.



Solution

Use SQL Server metadata to create the required DROP and CREATE scripts. The following process gathers the

metadata for check constraints. Then it executes the DROP statements. After a data load, you can run the script to

re-create the check constraints.

1.



Create the table to hold the persisted metadata for the check constraints, using DDL

like the following (C:\SQL2012DIRecipes\CH14\tblMetaData_CheckConstraints.Sql):

IF OBJECT_ID('dbo.MetaData_CheckConstraints') IS NOT NULL

DROP TABLE dbo.MetaData_CheckConstraints;





837

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



CREATE TABLE CarSales_Staging.dbo.MetaData_CheckConstraints

(

SCHEMA_NAME NVARCHAR (128) NOT NULL,

TABLE_NAME NVARCHAR (128) NOT NULL,

COLUMN_NAME NVARCHAR (128) NOT NULL,

CheckConstraintName NVARCHAR (128) NOT NULL,

definition NVARCHAR(max) NULL,

) ;

GO

2.



Populate the metadata table for the foreign key constraints using the following code

snippet (C:\SQL2012DIRecipes\CH14\CheckConstraintMetadata.Sql):

INSERT INTO MetaData_CheckConstraints

(

SCHEMA_NAME

,TABLE_NAME

,COLUMN_NAME

,CheckConstraintName

,definition

)



SELECT

SCH.name AS SCHEMA_NAME

,TBL.name AS TABLE_NAME

,COL.name

,CHK.name AS CheckConstraintName

,CHK.definition



FROM

sys.schemas AS SCH

INNER JOIN sys.tables AS TBL

ON SCH.schema_id = TBL.schema_id

INNER JOIN sys.check_constraints CHK

ON TBL.object_id = CHK.parent_object_id

INNER JOIN sys.columns COL

ON CHK.parent_object_id = COL.object_id

AND CHK.parent_column_id = COL.column_id



WHERE

CHK.is_disabled = 0 ;



3.



DROP the check constraints in the destination database by running the following piece

of T-SQL (C:\SQL2012DIRecipes\CH14\DropCheckConstraints.Sql):

-- Create DROP statements



-- Drop table to hold script elements



IF OBJECT_ID('tempdb..#ScriptElements') IS NOT NULL

DROP TABLE tempdb..#ScriptElements;



CREATE TABLE #ScriptElements (ID INT IDENTITY(1,1), ScriptElement NVARCHAR(MAX))





838

www.it-ebooks.info



Chapter 14 ■ ETL Process Acceleration



INSERT INTO #ScriptElements



SELECT DISTINCT

'ALTER TABLE '

+ SCHEMA_NAME

+ '.'

+ TABLE_NAME

+ ' DROP CONSTRAINT '

+ CheckConstraintName



FROM

MetaData_CheckConstraints ;



-- Execute DROP scripts



DECLARE @DropFK NVARCHAR(MAX)



DECLARE DropFK_CUR CURSOR



FOR

SELECT ScriptElement FROM #ScriptElements ORDER BY ID



OPEN DropFK_CUR



FETCH NEXT FROM DropFK_CUR INTO @DropFK



WHILE @@FETCH_STATUS <> −1

BEGIN



EXEC (@DropFK)



FETCH NEXT FROM DropFK_CUR INTO @DropFK



END ;



CLOSE DropFK_CUR;

DEALLOCATE DropFK_CUR;

4.



Carry out the data load process to update the destination database.



5.



Using code like the following, re-create the foreign keys from the persisted metadata

(C:\SQL2012DIRecipes\CH14\CreateCheckConstraints.Sql):

-- Drop table to hold script elements



IF OBJECT_ID('tempdb..#ScriptElements') IS NOT NULL

DROP TABLE tempdb..#ScriptElements;



CREATE TABLE #ScriptElements (ID INT IDENTITY(1,1), ScriptElement NVARCHAR(MAX));



INSERT INTO #ScriptElements





839

www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

14-6. Storing Metadata, and Then Scripting and Executing DROP and CREATE Statements for Destination Database XML Indexes

Tải bản đầy đủ ngay(0 tr)

×