如何在表值函数中查找索引的大小

时间:2017-06-25 11:24:37

标签: sql sql-server

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

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

enter image description here

sys.indexes中还有一条记录:

enter image description here

通常我会使用此查询获取索引的大小:

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

但这次没有回复。

任何人都可以给我建议如何找到这样一个索引的大小吗?

2 个答案:

答案 0 :(得分:4)

是的,你可以找到这个索引的大小,但是你应该认为它只在一个批处理时间内生存,你应该在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的列名来区分它

答案 1 :(得分:1)

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

是的,你在sys.indexes中有一行告诉你索引属性,比如类型(群集或非群集),is_primary_key,is_unique等。

但是,sys.partitionssys.allocation_units中没有相应的行。这就是你的查询什么都不返回的原因。如果使用左连接替换内部连接,则会看到NULLTotalSpaceGB的一行。{/ p>

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

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

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

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

select * from fIndexSize()

我可以看到优化器在幕后创建临时表。好吧,它必须将行存储在某处,并存储在TempDB中。

因此,您应该使用sys.allocation_unitstempdb运行您的选择。

首先,我使用SQL Sentry Plan Explorer查看临时表的名称:

plan explorer

然后我针对TempDB运行了查询:

temp table sizes