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!