web-dev-qa-db-ja.com

sys.dm_db_index_physical_statsのエラー

Selectステートメントを実行して、インデックスの断片化の割合を取得していますが、エラーが発生しています。

    SELECT A.NAME,B.NAME,C.avg_fragmentation_in_percent 
      FROM SYS.TABLES A 
      INNER JOIN SYS.INDEXES B ON A.OBJECT_ID=B.object_id
      CROSS APPLY SYS.DM_DB_INDEX_PHYSICAL_STATS(DB_ID(),
        A.OBJECT_ID,B.INDEX_ID,0,DEFAULT) C
    WHERE B.NAME IS NOT NULL

そしてエラーは

メッセージ413、レベル16、状態1、行1
相関するパラメータまたはサブクエリは、インライン関数「SYS.DM_DB_INDEX_PHYSICAL_STATS」ではサポートされていません。
メッセージ413、レベル16、状態1、行1
相関するパラメータまたはサブクエリは、インライン関数「SYS.DM_DB_INDEX_PHYSICAL_STATS」ではサポートされていません。

2
user98113

80互換モードの場合は、次のものが必要です。

DECLARE @dbid int = DB_ID();

SELECT t.name, i.name, ps.avg_fragmentation_in_percent 
  FROM sys.tables AS t         -- why A???
  INNER JOIN sys.indexes AS i  -- why B???
    ON t.[object_id] = i.[object_id]
  CROSS APPLY sys.dm_db_index_physical_stats
    (@dbid,NULL,NULL,0,DEFAULT) AS ps -- why C???
WHERE ps.index_id = i.index_id
AND ps.[object_id] = t.[object_id]  
AND i.name IS NOT NULL;

100の場合、次のものが必要です。

SELECT t.name, i.name, ps.avg_fragmentation_in_percent 
  FROM sys.tables AS t         -- why A???
  INNER JOIN sys.indexes AS i  -- why B???
    ON t.[object_id] = i.[object_id]
  CROSS APPLY sys.dm_db_index_physical_stats
    (DB_ID(),NULL,NULL,0,DEFAULT) AS ps -- why C???
WHERE ps.index_id = i.index_id
AND ps.[object_id] = t.[object_id]  
AND i.name IS NOT NULL;

別の回答に投稿された関数 見栄えがよくて便利で、正しい回答が得られます。見積もりコストを測定するだけでも明らかに勝者ですが、注意してください。マルチステートメントTVFには多くの隠れたコストがあります。実際に先に進んでそれらを使用する場合(この場合、OPが組み込み関数でエラーメッセージを取得するのと同じ理由で、インラインTVFを使用できません)。コストの比較は次のとおりです。

enter image description here

(そして、個々のルックアップのコストとフィルターなしを示すためだけに):

enter image description here

余談ですが、 大文字小文字に注意してください (大文字のシステムオブジェクトや列名は使用しないでください)を使用し、 賢明なエイリアス を使用して、 ステートメント終了記号を使用

2
Aaron Bertrand

DBに次のような関数を作成します。

create function dm_db_index_physical_stats_tvf 
( 
@db_id int 
,@object_id int 
,@index_id int 
,@partition_number int 
,@mode int 
) 
returns @results TABLE ( 
[database_id] [smallint] NULL, 
[object_id] [int] NULL, 
[index_id] [int] NULL, 
[partition_number] [int] NULL, 
[index_type_desc] [nvarchar](60) NULL, 
[alloc_unit_type_desc] [nvarchar](60) NULL, 
[index_depth] [tinyint] NULL, 
[index_level] [tinyint] NULL, 
[avg_fragmentation_in_percent] [float] NULL, 
[fragment_count] [bigint] NULL, 
[avg_fragment_size_in_pages] [float] NULL, 
[page_count] [bigint] NULL, 
[avg_page_space_used_in_percent] [float] NULL, 
[record_count] [bigint] NULL, 
[ghost_record_count] [bigint] NULL, 
[version_ghost_record_count] [bigint] NULL, 
[min_record_size_in_bytes] [int] NULL, 
[max_record_size_in_bytes] [int] NULL, 
[avg_record_size_in_bytes] [float] NULL, 
[forwarded_record_count] [bigint] NULL, 
[compressed_page_count] [bigint] NULL
) 
begin 
insert into @results 
select * 
from sys.dm_db_index_physical_stats (@db_id, @object_id, @index_id ,@partition_number ,@mode ) 
return 
end

そして今、あなたのメインクエリを実行します:

 SELECT A.NAME,B.NAME,C.avg_fragmentation_in_percent 
      FROM SYS.TABLES A 
      INNER JOIN SYS.INDEXES B ON A.OBJECT_ID=B.object_id
      CROSS APPLY dm_db_index_physical_stats_tvf(DB_ID(),
        A.OBJECT_ID,B.INDEX_ID,0,DEFAULT) C
    WHERE B.NAME IS NOT NULL  

SQL 2012環境でこれをテストしましたが、正常に動作します。

参照: http://sqlblogcasts.com/blogs/simons/archive/2006/11/28/dmvs-and-CROSS-APPLY.aspx

2
SQLPRODDBA