T-SQLを使用して、インデックスの再構築と再編成を自動化しています。オンラインで再構築できないインデックスに関する問題に遭遇しました。これは主に、ntext/nvarchar列が含まれているために発生します。
これらをこのステートメントの一部としてプログラムで識別する方法はありますか? WHERE述語への一種の追加
SELECT
--TOP 20
OBJECT_NAME(IPS.OBJECT_ID) AS [TableName], avg_fragmentation_in_percent, SI.name [IndexName],
schema_name(ST.schema_id) AS [SchemaName], 0 AS IsProcessed
INTO #FramentedTableList
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL , NULL) IPS
JOIN sys.tables ST WITH (nolock) ON IPS.OBJECT_ID = ST.OBJECT_ID
JOIN sys.indexes SI WITH (nolock) ON IPS.OBJECT_ID = SI.OBJECT_ID AND IPS.index_id = SI.index_id
WHERE ST.is_ms_shipped = 0 AND SI.name IS NOT NULL
AND avg_fragmentation_in_percent >= CONVERT(DECIMAL, @FragmentationThresholdForReorganizeTableLowerLimit)
ORDER BY avg_fragmentation_in_percent DESC
これをWHERE
句に追加して、LOBタイプを含むインデックスを除外できます(すべてキャプチャしたと思います)。
AND NOT EXISTS (
SELECT 1 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
AND ((c.system_type_id IN (34,35,99,241)) -- image, text, ntext, xml
OR (c.system_type_id IN (167,231,165) -- varchar, nvarchar, varbinary
AND max_length = -1))
WHERE ic.object_id = SI.object_id
AND ic.index_id = SI.index_id
)
SQL Server 2008または2008 R2を使用している場合、geography
およびgeometry
を取得するために、タイプ検索を次のように変更できます(credit Kenneth Fisher ) :
AND ((c.system_type_id IN (34,35,99,241)) -- image, text, ntext, xml
OR (c.system_type_id IN (167,231,165) -- varchar, nvarchar, varbinary
AND max_length = -1)
OR (c.user_type_id IN (129,130))) -- geometry, geography
もちろん、クエリを再構築してオンラインで使用できるインデックスを再構築し、メンテナンスの対象から除外できないインデックスを残さない方が賢明な場合があります。しかし、私はマックスに同意します、車輪を再発明しないでください。 Olaのスクリプトを入手してください。さらに強力なものが必要な場合は、お知らせください。
以下を使用してLOBを検出します。
SET @LOBCount = (
SELECT COUNT(*) FROM (
select t.name as TableName, i.name as IndexName, c.name as ColumnName, ty.name, ic.is_included_column
from [' + @DatabaseName + '].sys.indexes i
INNER JOIN [' + @DatabaseName + '].sys.tables t ON t.object_id = i.object_id
inner join [' + @DatabaseName + '].sys.index_columns ic on i.object_id = ic.object_id and i.index_id = ic.index_id
inner join [' + @DatabaseName + '].sys.columns c on ic.object_id = c.object_id and ic.column_id = c.column_id
INNER JOIN [' + @DatabaseName + '].sys.types ty ON c.system_type_id = ty.system_type_id
where
t.name = ''' + @TableName + '''
AND i.name = ''' + @IndexName + '''
AND (
ty.name IN (''text'', ''ntext'', ''image'')
or
(
ty.name IN (''varchar'', ''nvarchar'', ''varbinary'', ''xml'')
AND c.max_length = -1
)
)
) as x
)';
明らかに、これは、インデックスの再構築や再編成に使用するはるかに大きなストアドプロシージャからのコードフラグメントです。 Ola Hallengrenのスクリプトを次の場所で確認することをお勧めします http://ola.hallengren.com/
具体的には、WHERE句のNOT EXISTSを確認してください。
SELECT
--TOP 20
OBJECT_NAME(IPS.OBJECT_ID) AS [TableName], avg_fragmentation_in_percent,
SI.name [IndexName], schema_name(ST.schema_id) AS [SchemaName],
0 AS IsProcessed
INTO #FramentedTableList
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL , NULL) IPS
JOIN sys.tables ST WITH (nolock)
ON IPS.OBJECT_ID = ST.OBJECT_ID
JOIN sys.indexes SI WITH (nolock)
ON IPS.OBJECT_ID = SI.OBJECT_ID AND IPS.index_id = SI.index_id
WHERE ST.is_ms_shipped = 0 AND SI.name IS NOT NULL
AND avg_fragmentation_in_percent >=
CONVERT(DECIMAL, @FragmentationThresholdForReorganizeTableLowerLimit)
AND NOT EXISTS (
SELECT 1
FROM sys.index_columns
JOIN sys.columns
ON sys.index_columns.column_id = sys.columns.column_id
AND sys.columns.object_id = sys.index_columns.object_id
JOIN sys.types
ON sys.types.system_type_id = sys.columns.system_type_id
WHERE sys.index_columns.index_id = SI.index_id -- Join to get the correct index
AND sys.index_columns.object_id = ips.object_id -- Join to get the correct table
AND (sys.types.name IN ('text','ntext','xml','image','geometry','geography')
OR (sys.types.name IN ('varchar','nvarchar','varbinary')
AND sys.columns.max_length = -1) -- means MAX
)
)
ORDER BY avg_fragmentation_in_percent DESC