既存のデータベースには、PRIMARYファイルグループに多数のテーブルが格納されています。テーブル名の "プレフィックス"に応じて、これらのテーブルとそのインデックスを別のファイルグループに自動的に移動したいと考えています。
たとえば、次のような名前の5つのテーブルがあるとします。
ABC_XXXX
ABC_YYYY
DEF_ZZZZ
DEF_TTTT
GHI_UUUU
ABC
で始まるすべてのテーブルはファイルグループFG1
に、DEF
はファイルグループFG2
に、その他のテーブルはファイルグループDEFAULT
に移動する必要があります。
これは、コマンドCREATE INDEX
を使用して実行できます。
CREATE (UNIQUE|CLUSTERED|) INDEX <Index Name> ON <Table Name>(<Index Columns>)
WITH (DROP_EXISTING = ON) ON <New Filegroup>
このコマンドの最大の問題は、各インデックスの列を適切な順序で取得することです。
説明から省いていることがたくさんありますが、スクリプトはこれに対応する必要があります-インデックスは主キーですか、一意制約ですか?降順の列はありますか?インデックスはフィルタリングされていますか? INCLUDE列はありますか?スクリプトを手動で生成することは確かに可能ですが、スクリプトの生成ウィザードを使用してみませんか?
これで、すべてのスクリプトを含むクエリウィンドウができました。一部を削除し、他のスクリプトを手動でマッサージする必要がありますが、PKの一部ではないインデックスについては、単に検索して置換できるはずです。 DROP_EXISTING = OFF
をDROP_EXISTING = ON
に変換し、次に[PRIMARY]
をFG1
に交換します...
以下は、sys.indexes
、sys.columns
、およびsys.index_columns
を使用するスクリプトです。明示的な主キーが存在する場合は、一意のインデックスを作成します(「re- DROP_EXISTING
"構文でPKを作成します)。これは、インクルード列、Fill Factorを扱い、列を正しい順序に配置し、一意/クラスター化インデックスを最初に構築することも保証します。
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';
;WITH src AS
(
SELECT
obj = QUOTENAME(OBJECT_SCHEMA_NAME(i.[object_id]))
+ '.' + QUOTENAME(OBJECT_NAME(i.[object_id])),
i.[object_id],
i.index_id,
i.name,
uniq = CASE i.is_unique WHEN 1 THEN ' UNIQUE' ELSE '' END,
type_desc = i.type_desc COLLATE SQL_Latin1_General_CP1_CI_AS,
ff = ', FILLFACTOR = ' + CONVERT(VARCHAR(3), i.fill_factor),
dest = CASE LEFT(OBJECT_NAME(i.[object_id]), 3)
WHEN 'ABC' THEN 'FG1'
WHEN 'DEF' THEN 'FG2'
ELSE 'DEFAULT'
END
FROM sys.indexes AS i
INNER JOIN sys.partitions AS p
ON i.[object_id] = p.[object_id]
AND i.index_id = p.index_id
WHERE i.index_id > 0
-- AND OBJECT_NAME(i.object_id) IN ('list','of','tables')
),
cols AS
(
SELECT
name = QUOTENAME(c.name),
ic.key_ordinal,
ic.[object_id],
ic.index_id,
sort = CASE ic.is_descending_key WHEN 1 THEN ' DESC' ELSE ' ' END,
ic.is_included_column
FROM sys.index_columns AS ic
INNER JOIN sys.columns AS c
ON ic.[object_id] = c.[object_id]
AND ic.column_id = c.column_id
WHERE ic.[object_id] IN (SELECT [object_id] FROM src)
)
SELECT @sql = @sql + CHAR(13) + CHAR(10)
+ N'CREATE ' + uniq + ' ' + type_desc + ' INDEX ' + QUOTENAME(name)
+ ' ON ' + obj + '(' + STUFF((SELECT ',' + name + sort FROM cols
WHERE cols.object_id = src.object_id
AND cols.index_id = src.index_id
AND cols.is_included_column = 0
ORDER BY cols.key_ordinal
FOR XML PATH('')), 1, 1, '') + ')'
+ COALESCE(' INCLUDE(' + STUFF((SELECT ',' + name FROM cols
WHERE cols.[object_id] = src.[object_id]
AND cols.index_id = src.index_id
AND cols.is_included_column = 1
ORDER BY cols.key_ordinal
FOR XML PATH('')), 1, 1, '') + ')', '')
+ ' WITH (DROP_EXISTING = ON' + ff
+ ') ON ' + dest + ';'
FROM src
ORDER BY uniq DESC, type_desc;
SELECT @sql;
-- EXEC sp_executesql @sql;
完全を期すために、ここにsys.partitions
と、フィルター選択されたインデックスやデータ圧縮などのいくつかのSQL Server 2008固有の機能を追加するスクリプトを示します。
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';
;WITH src AS
(
SELECT
obj = QUOTENAME(OBJECT_SCHEMA_NAME(i.[object_id]))
+ '.' + QUOTENAME(OBJECT_NAME(i.[object_id])),
i.[object_id],
i.index_id,
i.name,
uniq = CASE i.is_unique WHEN 1 THEN ' UNIQUE' ELSE '' END,
type_desc = i.type_desc COLLATE SQL_Latin1_General_CP1_CI_AS,
filter = CASE WHEN i.has_filter = 1 THEN ' WHERE ' + i.filter_definition ELSE '' END,
ff = ', FILLFACTOR = ' + CONVERT(VARCHAR(3), i.fill_factor),
dc = CASE p.data_compression_desc WHEN 'NONE' THEN ''
ELSE ', DATA_COMPRESSION = ' + p.data_compression_desc END,
dest = CASE LEFT(OBJECT_NAME(i.[object_id]), 3)
WHEN 'ABC' THEN 'FG1'
WHEN 'DEF' THEN 'FG2'
ELSE 'DEFAULT'
END
FROM sys.indexes AS i
INNER JOIN sys.partitions AS p
ON i.[object_id] = p.[object_id]
AND i.index_id = p.index_id
WHERE i.index_id > 0
-- AND OBJECT_NAME(i.object_id) IN ('list','of','tables')
),
cols AS
(
SELECT
name = QUOTENAME(c.name),
ic.key_ordinal,
ic.[object_id],
ic.index_id,
sort = CASE ic.is_descending_key WHEN 1 THEN ' DESC' ELSE ' ' END,
ic.is_included_column
FROM sys.index_columns AS ic
INNER JOIN sys.columns AS c
ON ic.[object_id] = c.[object_id]
AND ic.column_id = c.column_id
WHERE ic.[object_id] IN (SELECT [object_id] FROM src)
)
SELECT @sql = @sql + CHAR(13) + CHAR(10)
+ N'CREATE ' + uniq + ' ' + type_desc + ' INDEX ' + QUOTENAME(name)
+ ' ON ' + obj + '(' + STUFF((SELECT ',' + name + sort FROM cols
WHERE cols.object_id = src.object_id
AND cols.index_id = src.index_id
AND cols.is_included_column = 0
ORDER BY cols.key_ordinal
FOR XML PATH('')), 1, 1, '') + ')'
+ COALESCE(' INCLUDE(' + STUFF((SELECT ',' + name FROM cols
WHERE cols.[object_id] = src.[object_id]
AND cols.index_id = src.index_id
AND cols.is_included_column = 1
ORDER BY cols.key_ordinal
FOR XML PATH('')), 1, 1, '') + ')', '')
+ filter + ' WITH (DROP_EXISTING = ON' + ff + dc
+ ') ON ' + dest + ';'
FROM src
ORDER BY uniq DESC, type_desc;
SELECT @sql;
-- EXEC sp_executesql @sql;