Esta é estranha… ou não.
Só quem nunca passou por ela é que duvida. Eu já passei por ela.
Estava a falar sobre isto com um colega que ainda não passou e que, naturalmente, duvidou.
Nada como mostrar que é possível.
Criamos uma tabela sem índice clustered, apenas um nonclustered. Heap mais simples não vão encontrar…
create table TesteHeap1 ( id bigint , valor bigint ) go create nonclustered index nci_t on TesteHeap1 (id) go
Inserimos alguns valores.
insert into TesteHeap1 select ABS(CHECKSUM(NEWID())) , ABS(CHECKSUM(NEWID())) from sys.objects a cross join sys.objects b
No meu caso, 24025 linhas.
Vamos ver o que temos por lá.
set statistics io, time on select * from TesteHeap1


75 logical reads para as 24025 linhas.
E tamanho?
exec sp_spaceused 'TesteHeap1'

Para já, nada de estranho.
Vamos a mais uns inserts?
insert into TesteHeap1 select ABS(CHECKSUM(NEWID())) , ABS(CHECKSUM(NEWID())) from sys.objects a cross join sys.objects b
E agora fazemos um delete.
delete from TesteHeap1 where valor > 100000
Aqui no meu caso “foram-se” 48047 linhas. Com o que é que ficámos?

3 linhas! E quantos reads?

18 reads para as 3 linhas. Tanto para tão pouco, não acham?
E espaço?
exec sp_spaceused 'TesteHeap1'

Tanto para tão pouco, não acham (v2) ?
Mais uma rodada de inserts.
insert into TesteHeap1 select ABS(CHECKSUM(NEWID())) , ABS(CHECKSUM(NEWID())) from sys.objects a cross join sys.objects b
select * from TesteHeap1

exec sp_spaceused 'TesteHeap1'

Mais 3 linhas do que na primeira vez e um pouco mais espaço também.
É só mais uma para o caminho…
insert into TesteHeap1 select ABS(CHECKSUM(NEWID())) , ABS(CHECKSUM(NEWID())) from sys.objects a cross join sys.objects b
select * from TesteHeap1

exec sp_spaceused 'TesteHeap1'

delete from TesteHeap1 where valor > 1000000000
Apagámos 25816 linhas… com o que é que ficamos?
select * from TesteHeap1

exec sp_spaceused 'TesteHeap1'

Analizando os dados depois do 1º insert e agora depois deste delete…
linhas | reads | data | index | unused | reserved | |
1º insert | 24025 | 75 | 600K | 552K | 208K | 1360K |
Agora | 22237 | 158 | 1264K | 1576K | 404K | 3280K |
Ou seja, menos dados, mais páginas, mais espaço.
Para referência, o que acontecerá se apagarmos todas as linhas?
A tabela vai ficar vazia… será?
delete from TesteHeap1

exec sp_spaceused 'TesteHeap1'

Mesmo “vazia” não está vazia, claramente.
E com um REBUILD?
alter table TesteHeap1 rebuild
select * from TesteHeap1

exec sp_spaceused 'TesteHeap1'

Finalmente está “vazia”.
Agora não se metam a fazer REBUILD a todas as vossas heaps em PROD, ok?