分配单元 ID 计算不正确?

ala*_*ncc 2 sql-server database-internals

我正在阅读关于如何根据 m_indexId 计算分配单元 ID的文章http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-how-are-allocation-unit-ids-calculated/和 m_objID。然后我通过执行以下命令在我的数据库之一上尝试:

    DBCC TRACEON(3604);
    DBCC PAGE (UFDATA_008_2013, 1, 73057, 3);
    GO
Run Code Online (Sandbox Code Playgroud)

输出结果是:

    PAGE HEADER:


    Page @0x10008000

    m_pageId = (1:73057)                 m_headerVersion = 1                  m_type = 1
    m_typeFlagBits = 0x0                 m_level = 0                          m_flagBits = 0x8000
    m_objId (AllocUnitId.idObj) = 1913890731                                  m_indexId (AllocUnitId.idInd) = 0
    Metadata: AllocUnitId = 406903719657472                                   Metadata: PartitionId = 406903719657472
    Metadata: IndexId = 1                Metadata: ObjectId = 1913890731      m_prevPage = (1:92774)
    m_nextPage = (0:0)                   pminlen = 11                         m_slotCnt = 61
    m_freeCnt = 3241                     m_freeData = 4829                    m_reservedCnt = 0
    m_lsn = (4028:6215:30)               m_xactReserved = 0                   m_xdesId = (0:0)
    m_ghostRecCnt = 0                    m_tornBits = 0                        
Run Code Online (Sandbox Code Playgroud)

然后我用上面文章中的公式计算分配单元ID为(0 << 48) + (1913890731 << 16) = 125428742946816,不等于输出Metadata:AllocUnitId(406903719657472)。为什么?

我可以确认页面已分配,因为我使用以下命令列出分配给表“AADomDataColSet”的所有页面:

       DBCC TRACEON(3604);
       Dbcc ind(UFDATA_008_2013, ‘AADomDataColSet’, -1);
Run Code Online (Sandbox Code Playgroud)

结果如下:

AADomDataColSet 的输出结果

您可以找到分配给此对象的页面 (1, 73057)。

谢谢

Pau*_*ite 5

这似乎与 Paul 帖子的评论中讨论的案例相同。他指出原因是页面不再分配(注意元数据IndexId = 1,但m_indexid = 0)。

使用 Paul 的脚本解码分配单元 ID:

DECLARE @alloc BIGINT = 406903719657472;
DECLARE @index BIGINT;
 
SELECT @index =
    CONVERT (BIGINT,
        CONVERT (FLOAT, @alloc)
            * (1 / POWER (2.0, 48)) -- right shift, reciprocal of left shift
    );
SELECT
    CONVERT (BIGINT,
        CONVERT (FLOAT, @alloc - (@index * CONVERT (BIGINT, POWER (2.0, 48))))
            * (1 / POWER (2.0, 16)) -- right shift, reciprocal of left shift
    ) AS [m_objId],
    @index AS [m_indexId];
Run Code Online (Sandbox Code Playgroud)

结果:

结果截图

这与DBCC PAGE输出中的 m_objid 匹配。

更新的问题

如果使用索引 ID 1,计算是正确的,再次使用保罗帖子中的公式:

SELECT allocation_id =
    1 * CONVERT (BIGINT, POWER (2.0, 48)) | -- index id
    1913890731 * CONVERT (BIGINT, POWER (2.0, 16)); -- object id
Run Code Online (Sandbox Code Playgroud)

分配id结果

因此,您的实际问题似乎根本与分配单位计算无关;相反,您是在问为什么DBCC PAGE显示 m_indexId (AllocUnitId.idInd) = 0页面已分配并与索引 1 相关联 - 如DBCC IND输出所示。

那个,我不知道。我所知道的是,计算对我来说是双向的,在 SQL Server 2012 build 6518 上进行测试。也许你的 SQL Server 版本或表有一些问题,这意味着AllocUnitId.idInd没有正确报告。如果没有具体的、可重复的细节,您可能需要问问保罗本人(尽管他目前正在度假)。

这可能是一些边缘情况。例如,这篇文章m_indexId如果数据库是从 SQL Server 2000 升级的,可能会有所不同。尝试重建表,这通常可以解决这些问题。