私のXMLインデックスはsys.dm_db_index_usage_stats
にリストされていません
これは、それらが使用されていないことを意味しますか?または、この特定のDMVはXMLインデックスの使用を追跡しませんか? (Books Onlineは質問に答えていないようです)
それらがsys.dm_db_index_operational_stats
によって追跡されていない場合、それらがどれだけ使用されているか、または現在どのキャッシュプランがそれらを使用しているかを知る別の方法はありますか?
私はあなたが経験していることを再現しようとしましたが、残念ながらそれを実現できませんでした(この回答の2番目の部分を参照してください)。これがバージョン間のバグ修正である場合、それはかなり文書化されていませんでした。これをGoogleで実行しても、まったく何も生成されませんでした。
問題は、実行している分析クエリがsys.dm_db_index_usage_stats
をsys.tables
に結合していることだと思います。 XMLインデックスは、通常のクラスター化インデックスおよび非クラスター化インデックスと同じ関係をベーステーブルと持たないことを除けば、合理的に聞こえます。
XMLインデックスが機能する方法では、インデックスはベーステーブルに対してまったく作成されません。プライマリXMLインデックスを作成すると、XMLデータから生成されるノードテーブルが具体化されます(つまり、クラスター化されたインデックスが作成されます)。セカンダリインデックスは、ノードテーブルの非クラスター化インデックスです。いいでしょういいので何ですかキャッチは、マテリアライズドノードテーブルが内部テーブルであり、sys.tables
に表示されないことです(代わりにsys.internal_tables
を参照してください)。したがって、DMVからのすべての行がクエリでOUTER JOIN
を使用して返されない限り、これらのインデックスの行がまったく返されない理由がわかります(それでも、名前を直接取得することはできません)。その行のテーブルの場合)。
正直なところ、私はXMLインデックスがどのように機能するかを最近知ったばかりなので、実際に戻って自分のインデックス分析スクリプトも再検討する必要があります(これらにはこの正確な欠陥があると思われます)。これは、問題を修正するために一緒に作成した簡単な基本スクリプトです。
SELECT
OBJECT_NAME(COALESCE(t.object_id, t2.object_id)) AS TableName,
i.name AS IndexName,
us.*
FROM sys.dm_db_index_usage_stats us
INNER JOIN sys.indexes i ON i.object_id = us.object_id AND i.index_id = us.index_id
LEFT OUTER JOIN sys.tables t ON t.object_id = us.object_id
LEFT OUTER JOIN sys.internal_tables it ON it.object_id = us.object_id
LEFT OUTER JOIN sys.tables t2 ON t2.object_id = it.parent_object_id
これは私のローカルインスタンス(64ビットDeveloperエディション、10.50.1617)に対して実行されました:
CREATE TABLE XmlIndexTest
(
Id int IDENTITY(1, 1) NOT NULL,
Data xml NOT NULL,
CONSTRAINT PK_XmlIndexTest
PRIMARY KEY CLUSTERED(Id)
)
GO
INSERT INTO XmlIndexTest(Data)
VALUES('<Invoice><LineItem Id="1" /></Invoice>')
CREATE PRIMARY XML INDEX IX_PrimaryXml ON XmlIndexTest(Data)
SELECT *
FROM XmlIndexTest
WHERE Data.exist('/Invoice/LineItem[@Id = 1]') = 1
SELECT i.name, us.*
FROM sys.dm_db_index_usage_stats us
INNER JOIN sys.indexes i ON i.object_id = us.object_id AND i.index_id = us.index_id
CREATE XML INDEX IX_SecondaryXml ON XmlIndexTest(Data)
USING XML INDEX IX_PrimaryXml FOR PATH
SELECT *
FROM XmlIndexTest
WHERE Data.exist('/Invoice/LineItem[@Id = 1]') = 1
SELECT i.name, us.*
FROM sys.dm_db_index_usage_stats us
INNER JOIN sys.indexes i ON i.object_id = us.object_id AND i.index_id = us.index_id
そしてこれらの結果を得ました:
プライマリおよびセカンダリXMLインデックスのobject_id
が、テーブルのクラスタ化インデックスのobject_id
とどのように異なるかに注意してください。
次のクエリは、特定の文字列を含むすべてのキャッシュされたプランを示しています。
WITH _a AS (
SELECT *
FROM sys.dm_exec_cached_plans _cp
WHERE EXISTS (
SELECT *
FROM sys.dm_exec_plan_attributes(_cp.plan_handle) _pa
WHERE _pa.attribute = 'dbid'
AND value = DB_ID('MR_ARG_Ford')
)
)
SELECT OBJECT_NAME(objectid), *
FROM _a
CROSS APPLY sys.dm_exec_query_plan(_a.plan_handle)
WHERE convert(nvarchar(max), query_plan) like '%Name_of_your_XML_Index%'
XMLインデックスの名前を含むキャッシュされたプランを見つけたので、インデックスが使用されていることはかなり確実です。つまり、sys.dm_db_index_usage_stats
は、実際にはXMLインデックスの使用状況を追跡しません。
誰かがこれを支持/反論するためのリンクを見つけることができれば、それはありがたいです。