SQL Serverの統計は物理的にどこに保存されますか?


27

クエリオプティマイザーが使用する統計情報は、SQL Serverデータベースファイルとバッファープール内に物理的に保存されていますか?

より具体的には、DMVやDBCCを使用して統計で使用されるページを把握する方法はありますか?

SQL Server 2008 InternalsとSQL Server Internals and Troubleshootingの両方の書籍を所有していますが、いずれも統計の物理構造については説明していません。もしそうなら、私はこの情報を見つけることができません。


1
データベースの統計のみのコピーを作成すると、それSTATS_STREAMがファイル自体で見つけられるものであるかどうかを調べたことがないバイナリが表示されます。
マーティンスミス

2
統計はStatMan、blobを出力する内部専用の集計関数()によって作成されます(皮肉なことに、その名前はSSMSクエリウィンドウで関数として強調表示されます)。論理的には、統計はインデックスまたはテーブル列のセットに関連付けられているため、内部メタデータテーブルを調べて、BLOBにつながる列binaryまたはvarbinary列を探します。これはを使用して表示できるはずですがDBCC PAGE、すべて内部にあるため、おそらく他の方法では表示できません。
ジョンセイゲル

1
@ivanmp初心者DBAの多くはBPやQOが何であるかを知らないので、明確にするために質問を編集しました。
マックスヴァーノン

2
sysindexes.statblob以前は存在していましたが、2005年以降に戻りNULL、場所は完全に文書化されていませんDBCC SHOW_STATISTICS(o, i) WITH STATS_STREAM;
アーロンバートランド

1
インデックスの統計を見つけました-それらは入っていますsys.sysidxstats-そのテーブルにLOBポインターがあるように見えます。列の統計情報がまだどこにあるのかわかりません。それらはtype列があるだけでなく、そのテーブルにある可能性があります。
ジョンセイゲル

回答:


30

それらを見つけました。

  1. 単純な統計オブジェクトを使用してテーブルを作成します。

    CREATE DATABASE splunge;
    GO
    USE splunge;
    GO
    CREATE TABLE dbo.foo(bar INT, munge INT);
    GO
    CREATE STATISTICS x ON dbo.foo(bar);
    CREATE STATISTICS y ON dbo.foo(munge);
    GO
    INSERT dbo.foo SELECT s1.[object_id], s2.[object_id]
      FROM sys.objects AS s1
      CROSS JOIN sys.objects AS s2;
    GO
    UPDATE STATISTICS dbo.foo;
    GO
  2. DAC(ADMIN:Server[\instance])を使用して接続します。

  3. 次のクエリを実行します。

    DBCC SHOW_STATISTICS('dbo.foo', 'x') WITH STATS_STREAM;
    DBCC SHOW_STATISTICS('dbo.foo', 'y') WITH STATS_STREAM;
    
    SELECT name, imageval 
      FROM sys.stats AS s
      INNER JOIN sys.sysobjvalues AS o
      ON s.object_id = o.objid
      AND s.stats_id = o.subobjid
    WHERE 
      s.object_id = OBJECT_ID('dbo.foo');

imagevalstatsオブジェクトごとにstats blobと同じではない、stats blob が含まれていることに注意してください。これは単なるオフセットです。私のシステムでは、xに対してこれをもたらしました(明らかにかなりのビットを切り捨てました)。

0x0100...bunch of chars...000007000000C4E1BE00EEA0...rest the same
                            0x07000000C4E1BE00EEA0...rest the same

そして、これはyに対して:

0x0100...bunch of chars...430007000000C7E1BE00EEA0...rest the same
                            0x07000000C7E1BE00EEA0...rest the same

同じことがインデックスベースの統計にも当てはまりました。

DBCCコマンドを使用して一連のクエリを実行すると、おそらくこれをさらに検証できます。最初に、クラスター化インデックスに関係するページを見つけsys.sysobjvaluesます(データベース名を置き換えます)。

DBCC IND('splunge', 'sys.sysobjvalues', 1);

結果には多数のページがリストされます。興味があるのはのページですPageType = 1。新しいデータベースを使用すると、最も高いPagePID値を持つページの1つでこの情報を見つけることができるはずです。たとえば、私のシステムではこれはページ281だったので、そのページを詳しく調べました。

DBCC TRACEON(3604);

DECLARE @dbid INT = DB_ID();

DBCC PAGE(@dbid, 1, 281, 3);

DBCC TRACEOFF(3604);

案の定、スロット17のデータが見つかりました。

DBCCページの部分的な結果

(より大きなデータベースでは、新しい統計オブジェクトでさえ新しい(新しい)ページで終わるという保証がないため、より多くのハンティングとペッキングが必要になる場合があります。)

自宅でこれを試してみてください。しかし、このためにDACに接続する必要がある理由があります。もちろん、DBCC SHOW_STATISTICS出力ではできなかったこの情報で何をするつもりなのか知りたいです。

もちろん、これはSTATS_STREAMヒストグラムやその他の情報を提供するためにデコードしようとせず、表形式の出力がDBCC SHOW_STATISTICS ... WITH HISTOGRAMテーブル形式のどこかに保存されているという証拠を見つけることができなかったことに注意してください。Joe Changは、それがあなたが望んでいるものである場合、デコードに関するいくつかの情報を持っています。クエリでやりたいことだとは思わない-を使用するだけDBCCです。


2
私たちには勝者の皆さんがいます。私はあなたに帽子を傾けます。
ゼーン

ハハハ、おめでとう、ありがとう、先生!心配しないで、私はすべきでないことは何もしていません(別名「バカ」)。個人的な成長のためだけです。どこにもこれについて何も見つからないことに気付いたとき、私はそれに興味を持ちました。=)
ivanmp

ジョー・チャンの記事について、これに対する答えを探していたときに見つけました。すでに読み始めていました。再度、感謝します。:)
ivanmp
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.