Autoincrementanti e numeri negativi. Non piacciono proprio?

Published 26 febbraio 09 10.37 | abenedetti

Spesso ci si dimentica che, nella gestione dei campi contatore, abbiamo a disposizione anche i numeri minori di zero.

Spesso, se ci si trova nell'eventualità di dover memorizzare 3 miliardi e mezzo di righe, si preferisce utilizzare, sulla colonna contatore autoincrementante, un tipo BIGINT.

Perchè?
Perchè il tipo INT arriva, all’estremo positivo, fino a 2.147.483.647

Bene. E' la parte negativa?

Perchè siamo abituati a scrivere qualcosa come questo?

create table test
(
idRecord int primary key identity (1,1),
valore varchar(1)
)
go 

e non qualcosa come questo?

create table test
(
idRecord int primary key identity (-2147483648,1),
valore varchar(1)
)
go 

La domanda che mi faccio spesso è: perchè i numeri negativi non piacciono?
Non sono forse cifre come tutte le altre?

Si tratta solo di leggibilità?
Si ha paura di dire "guarda la riga con ID = -1.235.887.112 ?"

Il punto è sempre e solo questo: I/O.

Dobbiamo risparimiare storage. Non perchè costi lo spazio di per sè (non si parla di euro per hard disk), ma perchè costa tantissimo utilizzarlo (leggerlo / scriverlo).

Se utilizzo un BIGINT significa utilizzare 4 byte in più.
Ovvero, con tre miliardi di righe significa utilizzare 12 miliardi di byte, ovvero più di 11 Gb!!!

E' proprio necessario?
Vogliamo vedere cosa succede "solo" con 50.000 righe (e non miliardi)?

set nocount on
set statistics io off
use tempdb
go 

create table testPos
(
idRecord bigint primary key identity (1,1),
valore char(5)
)
go 

create table testNeg
(
idRecord int primary key identity (-2147483648,1),
valore char(5)
)
go 

declare @i int = 50000
while (@i > 0)
begin
   
insert testPos values ('a')
   
insert testNeg values ('a')
   
set @i -= 1
end 

set statistics io on 

select COUNT(1) from testPos
select COUNT(1) from testNeg 

--> testPos: logical reads 138
--> testNeg: logical reads 114
--> 24 letture di differenza! 

set statistics io off 

;with cte as
(
   
select * from sys.dm_db_index_physical_stats(db_id(), 
       
object_id('dbo.testPos'), NULL, NULL, 'DETAILED') where index_level = 0
   
union all
   
select * from sys.dm_db_index_physical_stats(db_id(), 
       
object_id('dbo.testNeg'), NULL, NULL, 'DETAILED') where    index_level = 0
)
select
   
object_name(object_id), index_depth, page_count, avg_record_size_in_bytes 
from
   
cte
go 

drop table testPos
drop table testNeg
go

image 

Con 50.000 righe, utilizzando un BIGINT, ho 24 data pages in più, ovvero 24 * 8 Kb = 192 Kb buttati.

Comments

# sgainz said on febbraio 27, 2009 12.19 :

ed ecco che esce fuori il genovese che è in te :)

# abenedetti said on febbraio 27, 2009 12.27 :

ma io non ho origini genovesi... :-)

# orsocurioso said on febbraio 27, 2009 03.18 :

Sgainz: non parlare male dei liguri... che per meta' io lo sono  (e un pezzo e' proprio "seneise")

;-)

This Blog

Syndication