Austerity e la patrimoniale sui bytes

In periodo di austerity mi chiedo solo perchè nessuno si preoccupi mai di “tagliare” i bytes in eccesso sui propri database… :-)

Non potremmo mettere tutta la nostra attenzione anche nella costruzione dei nostri database e risparmiare ciò che è inutile, superfluo e alla lunga dannoso?

Vi siete mai chiesti se avete bytes in eccesso?

 

Mi trovo spesso a verificare che la modellazione delle tabelle non rispecchia studi approfonditi (purtroppo, a volte, nemmeno studi superficiali).

E allora vedo …

  • colonne INT per memorizzare informazioni come [idRegioneItaliana] o la rappresentazione numerica di giorni , mesi, anni…
  • UNIQUEIDENTIFIER, magari cluster, al posto di interi autoincrementanti, che provocano uno spazio occupato folle (!) e una frammentazione inutile ed evitabile
  • colonne UNICODE a dimensione fissa per testi variabili e, soprattutto, “italici” (= ASCII)
  • colonne BIGINT utilizzate per rappresentare una data in forma intera, come “20121211” (quando poi qualcuno mi farà capire come si può scrivere una data che abbia più di 8 caratteri gliene sarei grato…)
  • date di transazioni, che non hanno bisogno di essere precisi al secondo, memorizzati con DATETIME

L’elenco potrebbe essere molto lungo, ma mi fermo.

 

Credo basti ricordare LA regola: utilizzare il tipo di dato più piccolo in grado di memorizzare l’informazione più grande.

Un’analisi precisa ed accurata (e quindi più lunga) non è una perdita di tempo.

Vorrei vedere un architetto a progettare fondamenta in modo tale che possano reggere qualsiasi peso avrà la casa (2 piani o 20?)

 

Il mio suggerimento?

Prendere una tabella che può essere rimodellata, crearne la “nuova versione”, popolarla con gli stessi dati, effettuare un rebuild e poi vederne le differenze.

Nell’esempio sotto prendo in considerazione il livello foglia dell’indice cluster per vedere i bytes occupati “prima” e “dopo” la cura:

 DECLARE @idObject int;
SET @idObject = ( SELECT OBJECT_ID( '<nome tabella>' ));
SELECT min_record_size_in_bytes , 
       max_record_size_in_bytes , 
       avg_record_size_in_bytes
  FROM sys.dm_db_index_physical_stats( DB_ID( ) , @idObject , NULL , NULL , 'detailed' )
  WHERE index_id = 1 AND index_level = 0;


SET @idObject = ( SELECT OBJECT_ID( '<nome tabella rimodellata>' ));
SELECT min_record_size_in_bytes , 
       max_record_size_in_bytes , 
       avg_record_size_in_bytes
  FROM sys.dm_db_index_physical_stats( DB_ID( ) , @idObject , NULL , NULL , 'detailed' )
  WHERE index_id = 1 AND index_level = 0;

Fatto questo verificare anche le differenze in termini di attività di I/O per vedere, in concreto, i benefici apportati:

 SET STATISTICS IO ON;
SELECT * FROM <nome tablle>;
SELECT * FROM <nome tabella rimodellata>;

 

E così, raccogliendo bytes e bytes su riga, per ogni tabella, si possono fare dei risparmi interessanti – anche inaspettati (“Non pensavo di trovare 20 GB in mezz’ora… ” (cit.)).

E i risparmi, per noi, non sono in termini di storage (mi interessano poco in realtà). Sono in termini di attività di I/O.

L’unico vero indice di performance di un database.

 

E così, a differenza dell’austerity reale, a vivere meglio sarete soprattutto voi!