web-dev-qa-db-ja.com

プログラムでオンラインで再構築できないインデックスを見つける

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 
5
reticentKoala

これを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のスクリプトを入手してください。さらに強力なものが必要な場合は、お知らせください。

2
Aaron Bertrand

以下を使用して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/

3
Max Vernon

具体的には、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 
3
Kenneth Fisher