【问题标题】:How to find size of index in table-valued function如何在表值函数中查找索引的大小
【发布时间】:2017-06-25 21:20:14
【问题描述】:

In article about sys.indexes有一句话表示这个观点

包含表格对象(例如表格)的每个索引或堆的一行, 视图或表值函数

我有兴趣找到这样一个索引的大小。

所以我用索引创建了函数:

create function fIndexSize()
returns @res table
(
  object_id int          not null
, name      varchar(128) not null
, primary key (object_id)
)
as
begin
    insert into @res
    select object_id, name
    from sys.objects
    where object_id > 255
return
end

这里我们可以看到新索引的名称:

sys.indexes中也有记录:

通常我使用这个查询获得索引的大小:

select
      o.schema_id
    , o.object_id
    , o.name
    , o.type_desc
    , sum (a.total_pages) * 8.00 / 1024 / 1024 as TotalSpaceGB
from sys.objects o
inner join sys.indexes i on o.object_id = i.object_id
inner join sys.partitions p on i.object_id = p.object_id and i.index_id = p.index_id
inner join sys.allocation_units a on p.partition_id = a.container_id
where (o.name = 'fIndexSize' or i.name like 'PK__fIndexSi%')
group by o.schema_id, o.object_id, o.name, o.type_desc

但这一次没有返回任何东西。

谁能给我建议如何找到这样一个索引的大小?

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    是的,你可以找到这个索引的大小,但你应该认为它只存在一个批次的时间,你应该在 tempdb 中查找它(因为它是表变量):

        create function fIndexSize()
        returns @res table
        (
          object_id_xxxx int          not null
        , name      varchar(128) not null
        , primary key (object_id_xxxx)
        )
        as
        begin
            insert into @res
            select object_id, name
            from sys.objects
            where object_id > 255
        return
        end;
    

        select i.name,
               c.name,
               8 * SUM(au.used_pages) as size_kb
        from tempdb.sys.indexes i
             join tempdb.sys.columns c
                on i.object_id = c.object_id
             join tempdb.sys.partitions as p 
                on p.object_id = i.object_id and p.index_id = i.index_id
             join tempdb.sys.allocation_units as au 
                on au.container_id = p.partition_id        
        where c.name = 'object_id_xxxx' 
        group by  i.name,
                  c.name
    

    我在这里留下列名只是为了表明找到的索引是我们要找的,我选择了带有xxxx的列名以便区分

    【讨论】:

      【解决方案2】:

      表值函数的结果不存储在数据库的永久表中。它是在查询执行期间动态生成的。

      是的,sys.indexes 中有一行告诉您索引属性,例如类型(是否聚集)、is_primary_key、is_unique 等。

      但是,sys.partitionssys.allocation_units 中没有对应的行。这就是您的查询不返回任何内容的原因。如果将内连接替换为左连接,您会看到一行 NULLTotalSpaceGB

      所以,文档是正确的。文档没有说表值函数在sys.allocation_units 中有行。

      函数的每次调用可能返回不同数量的行。这组行在查询运行之前不存在,在查询完成后也不存在。

      即使在函数执行期间,sys.partitionssys.allocation_units 对于此索引 (PK__fIndexSi...) 也是空的。

      当我查看查询的实际执行计划时

      select * from fIndexSize()
      

      我可以看到优化器在幕后创建了一个临时表。好吧,它必须将行存储在某个地方,并且它们存储在 TempDB 中。

      因此,您应该使用tempdbsys.allocation_units 运行您的选择。

      一开始我用 SQL Sentry Plan Explorer 来查看临时表的名称:

      然后我对 TempDB 运行您的查询:

      【讨论】:

      • 多语句表值函数存储在 sys.objects 中,类型为TF,但正如您所说,它没有实现,因此没有空间分配。查询内连接省略了对象,因为它在 sys.indexes 等中没有行。
      • @DanGuzman,经过一些实验,我确认表值函数的结果集在 tempdb 中实现,并且可以通过sys.allocation_units 获取其大小。我真的不知道如何在繁忙的服务器上找出相关临时表的名称。
      • 我不明白 OP 想要每个函数调用的临时空间。每个执行上下文的空间,而不是绑定到 TVF 本身。
      猜你喜欢
      • 1970-01-01
      • 2013-06-01
      • 2019-08-21
      • 2018-07-27
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多