统计信息物理存储在SQL Server中的什么位置?


27

查询优化器所使用的统计信息在哪里物理存储在SQL Server数据库文件和缓冲池中?

更具体地说,是否有一种方法可以找出使用DMV和/或DBCC的统计信息所使用的页面?

我同时拥有《 SQL Server 2008内部原理》和《 SQL Server内部原理与故障排除》一书,但都没有谈论统计的物理结构。如果没有,我将无法找到此信息。


1
当您创建仅统计信息的数据库副本时,它会显示二进制文件,但STATS_STREAM我从未调查过它是否可以在文件本身中找到。
马丁·史密斯

2
统计信息由仅内部聚合函数(StatMan)创建,该函数输出一个Blob(具有讽刺意味的是,该名称在SSMS查询窗口中被突出显示为函数)。从逻辑上讲,统计信息与索引或一组表列相关联,因此,我将从检查内部元数据表开始,以查找会导致斑点的binaryvarbinary列。应该可以使用来查看此内容DBCC PAGE,但可能无法通过其他任何方式查看,因为它全部是内部的。
乔恩·塞格尔

1
@ivanmp我为清楚起见编辑了您的问题,因为许多新手DBA都不知道BP或QO是什么。
Max Vernon 2012年

2
曾经在,sysindexes.statblob但是从2005年开始返回,NULL并且该位置完全未被记录,只能通过(据我所知)进行检索DBCC SHOW_STATISTICS(o, i) WITH STATS_STREAM;
亚伦·伯特兰

1
找到了索引状态(它们在其中sys.sysidxstats),好像该表中有一个LOB指针。我不确定列的统计信息在哪里;它们可以在该表中也可以有一个type列。
乔恩·塞格尔

Answers:


30

找到他们。

  1. 创建一个带有简单stats对象的表。

    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');
    

您会注意到,imageval对于每个stats对象,它与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值的页面之一上找到此信息。例如,在我的系统上,这是第281页,因此我仔细查看了该页面:

DBCC TRACEON(3604);

DECLARE @dbid INT = DB_ID();

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

DBCC TRACEOFF(3604);

果然,我在插槽17中找到了数据:

DBCC页面的部分结果

(在较大的数据库上,您可能不得不做更多的工作,因为无法保证即使是新的统计信息对象也将最终出现在新的(er)页面上。)

继续尝试在家中进行此操作,但是有一个原因需要为此与DAC连接。我很想知道,当然,您将如何处理这些信息,而DBCC SHOW_STATISTICS输出却无法做到这一点。

请注意,这当然不会尝试对进行解码STATS_STREAM以提供直方图或其他信息,并且我找不到任何证据证明其表格输出DBCC SHOW_STATISTICS ... WITH HISTOGRAM以表格式存储在任何地方。如果您要这样做,Joe Chang会提供一些有关解码的信息。我认为这不是您要在查询中执行的操作-只需使用即可DBCC


2
我们有一个赢家,女士们,先生们。先生,我给你戴帽子。
Zane

哈哈哈,恭喜,先生!不用担心,我没有做任何我不应该做的事情(又称“愚蠢”)。这只是为了个人成长。一旦意识到自己在任何地方都找不到任何东西,我便对此产生了浓厚的兴趣。=)
ivanmp

关于Joe Chang的文章,我在寻找答案的同时发现了。我已经开始阅读它。再次感谢。:)
ivanmp
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.