xVelocity in Deep 
Marco Pozzan 
twitter: @marcopozzan 
email: info@marcopozzan.it 
site: www.marcopozzan.it 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Sponsors 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Organizers 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Speaker info 
 MVP SQL Server 
 Presidente della community 1nn0va 
(www.innovazionefvg.net) 
 Project manager del reparto Business 
Intelligence presso CGN S.P.A. (www.cgn.it) 
 Docente ITS all’Università di Pordenone 
 Partecipo agli eventi community 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Agenda 
 Gestione delle query 
 Che cosa è xVelocity in-memory 
 Row vs Columnar storage 
 RLE e Dictionary Encoding 
 Uso memoria: memorizzazione, processing e 
query 
 Best practice 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Gestione delle query 
 Direct Query mode 
 Trasformazione da DAX a SQL 
 Query sul motore SQL Server 
 Molte limitazioni (solo connessione SQL, solo DAX no 
MDX, limiti DAX, no colonne calcolate, no security) 
 In Memory mode 
 Engine per elaborare formule DAX (formula engine 
DAX) 
 Storage Engine Vertipaq (xVelocity in-memory) 
 Sfrutta tutte le funzionalità di Tabular 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Gestione delle query 
DAX/MDX query 
Analysis 
Services 
2012 
Tabular 
Model 
DirectQuery 
Mode (Motore di 
query) 
In-Memory Mode 
(Motore di query) 
SQL Query 
Query 
Query 
Storage engine query 
Storage engine query 
Storage engine query 
 PROCESS = Lettura dalla sorgente dati 
 Vertipaq contiene il risultato del processing del 
database 
External 
Data 
Sources 
Process 
Vertipaq 
Storage 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Che cosa è xVelocity in-memory? 
 E’ un database in memoria (dati sono in memoria) 
 E’ basato su una metodologia relazionale 
 Database colonnare 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Come lavora un row storage 
Alloco spazio su disco 
(pagine) 
Id FirstName LastName BirthDate 
Marital 
Status 
Children 
1 Larry Gill 13/04/1977 00:00 M 1 
2 Geoffrey Gonzalez 06/02/1977 00:00 S 2 
3 Blake Collins 23/04/1975 00:00 M 0 
4 Alexa Watson 25/08/1977 00:00 S 0 
5 Jacquelyn Dominguez 27/09/1977 00:00 M 1 
6 Casey Gutierrez 17/12/1977 00:00 M 1 
7 Colleen Lu 17/07/1973 00:00 M 2 
8 Jeremiah Stewart 26/06/1979 00:00 S 1 
9 Leah Li 06/10/1976 00:00 S 0 
Id FirstName LastName BirthDate 
Marital 
Status 
Children 
1 Larry Gill 13/04/1977 00:00 M 1 
2 Geoffrey Gonzalez 06/02/1977 00:00 S 2 
3 Blake Collins 23/04/1975 00:00 M 0 
4 Alexa Watson 25/08/1977 00:00 S 0 
Alloco ancora spazio 
su disco perchè finito 
5 Jacquelyn Dominguez 27/09/1977 00:00 M 1 
6 Casey Gutierrez 17/12/1977 00:00 M 1 
7 Colleen Lu 17/07/1973 00:00 M 2 
8 Jeremiah Stewart 26/06/1979 00:00 S 1 
9 Leah Li 06/10/1976 00:00 S 0 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Caratteristiche di un row storage 
 SELECT * di una tabella 
 Legge tutta la tabella dalla prima all’ultima riga 
 SELECT SUM(children) della tabella 
 Legge tutta la tabella dalla prima all’ultima riga e poi 
si legge solo la colonna children per fare la somma 
 Prestazioni pessime per un dato piccolo devo fare 
tanto I/0 su disco che poi non serve 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Caratteristiche di un row storage 
 Il risultato della SELECT SUM(children) non cambia 
nemmeno se faccio I/O in memoria e non su disco 
 Trasferisco i dati dalla memoria alla cache della CPU 
dove si svolge il calcolo 
 La cache interna è molto limitata 
 Pessimo uso perché carico una grande parte di 
memoria per poi usarne un pezzettino 
 Ottengo comunque prestazioni peggiori rispetto al 
fatto di lavorare su dati più compatti (Problema) 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Soluzione con gli indici 
 Se devo fare spesso la SUM(children) 
 Creo un indice su children 
 La query richiede solo il campo children (l’indice 
copre la query), leggo solo l’indice e non tutta la 
tabella 
 L’indice contiene dati più compatti e mi aiuta per I/O 
 Gli indici in generale riducono il numero di colonne 
di una tabella e ottimizzano l’I/0 
Concetto di Column Storage 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Caratteristiche di un column storage 
 Portiamo il concetto di indice in memoria 
 Estremizziamo il concetto di indice 
Marital Status 
Id Id 
FirstName FirstName 
LastName 
BirthDate BirthDate 
Marital Status Children 
1 1 
Larry Larry 
Gill 
13/13/04/04/1977 1977 00:00:00 00 
M M 
1 
2 2 
Geoffrey Geoffrey 
Gonzalez 
06/06/02/02/1977 1977 00:00:00 00 
S S 
2 
3 3 
Blake Blake 
Collins 
23/23/04/04/1975 1975 00:00:00 00 
M M 
0 
4 4 
Alexa Alexa 
Watson 
25/25/08/08/1977 1977 00:00:00 00 
S S 
0 
5 5 
Jacquelyn Jacquelyn 
Dominguez 
27/27/09/09/1977 1977 00:00:00 00 
M M 
1 
6 6 
Casey Casey 
Gutierrez 
17/17/12/12/1977 1977 00:00:00 00 
M M 
1 
7 7 
Colleen Colleen 
Lu 
17/17/07/07/1973 1973 00:00:00 00 
M M 
2 
8 8 
Jeremiah Jeremiah 
Stewart 
26/26/06/06/1979 1979 00:00:00 00 
S S 
1 
9 9 
Leah Leah 
Li 
06/06/10/10/1976 1976 00:00:00 00 
S S 
0 
Un file per colonna 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Caratteristiche di un column storage 
 Faccio una SELECT SUM(children) della tabella 
 Non devo fare un indice 
 La colonna è già l’indice perché contiene solo 
children 
 Molto veloce 
 Faccio SELECT SUM(children) GROUP BY FirstName 
 Non è più così bello 
 Devo leggere due colonne: Children e FirstName 
 Devo poi unire il risultato pagando tempo di CPU 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Caratteristiche di un column storage 
 Rispetto alla row storage 
 più velocità se devo leggere una colonna 
 più velocità se leggo poche colonne 
 più lento se faccio SELECT * 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Column vs Row 
 Memorizzazione su colonna 
 Accesso veloce ad una singola colonna 
 Ho la necessità di materializzare le righe 
 Spendiamo CPU per ridurre I/0 (le CPU le possono 
fare più veloci o metterne tante ) 
 Memorizzazione per riga 
 Accesso veloce alla singola riga 
 Non necessita di materializzazione 
 Spendiamo l’I/O per ridurre la CPU (i dischi o la 
memoria non si possono fare più veloci ) 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Cambiare il modo di pensare (colonnare) 
 Siamo in un mondo in cui lo storage è fatto da una sola 
colonna . 
 Ci sono cose che si possono fare memorizzando i dati 
in colonna che sono più efficienti rispetto ai dati 
memorizzati su riga 
Sapete come funziona la compressione di SQL Server? 
 per riga (non fa grandi cose… pulizie spazi bianchi, ridurre 
caratteri unicode, ridurre i decimali …..) 
 per pagina (identifica all’interno della pagina parti uguali e 
le indicizza per poi comprimere la pagina creando un indice 
all’inizio) 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Compressione in Vertipaq 
 Vertipaq (simile compressione di pagina in SQL Server) 
 Identifica parti uguali nell’aria di memoria 
 Crea una struttura per rappresentare le parti uguali 
e ottiene la struttura compressa della colonna 
 Più efficiente di SQL perché si ragiona solo su una 
colonna con pochi valori distinti rispetto alla pagina 
di SQL in cui ho righe con più colonne e con meno 
valori distinti . 
Vediamo come Vertipaq esegue la compressione 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Run Length Encoding (RLE) - 1 livello 
Children 
1 
1 
1 
1 
1 
... 
2 
2 
2 
2 
2 
2 
2 
2 
.... 
Children Inizio Lunghezza 
1 1 200 
2 201 400 
FirstName 
Larry 
Larry 
Larry 
... 
Geoffrey 
Geoffrey 
Geoffrey 
... 
Alexa 
Alexa 
Alexa 
... 
Colleen 
Colleen 
... 
Potrei anche decidere di 
togliere la colonna inizio 
e tenere solo la fine 
FirstName Lunghezza 
Larry 400 
Geoffrey 400 
Alexa 100 
Colleen 100 
BirthDate 
13/04/1977 
13/05/1977 
13/06/1977 
.... 
15/04/1980 
16/04/1947 
13/04/1976 
... 
13/04/1976 
13/04/1976 
13/04/1976 
... 
13/04/1990 
13/04/1934 
... 
BirthDate lunghezza 
13/04/1977 1 
13/05/1977 1 
13/06/1977 1 
.... 
15/04/1980 1 
16/04/1947 1 
13/04/1976 1 
... 
13/04/1976 1 
13/04/1976 1 
13/04/1976 1 
... 
13/04/1990 1 
13/04/1934 1 
... 
Le date cambiano così di frequente che se 
provassi a comprimerla avrei su lunghezza 
tutti 1 e otterrei una tabella più grande 
dell’originale Vertipaq lascia l’originale. 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Run Length Encoding (RLE) - 1 livello 
 Vertipaq non usa mai più memoria rispetto alla colonna 
sorgente…se non riesce a comprimerla la lascia come è 
 Vertipaq durante il processing di un tabella 
 Divide la tabella in colonne 
 Comprime ogni colonna con RLE 
 Attenzione!!! L’ordinamento delle colonne deve 
essere lo stesso per ogni colonna perchè devo 
materializzare i dati delle varie colonne (se ne 
occupa vertipaq ) buon ordinamento = buona 
compressione 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Dictionary encoding - 2 livello 
 Più importante di RLE 
 Vediamo i passi per creare il Dictionary 
1. Vertipaq legge una colonna di tipo stringa 
2. Effettua il distinct della colonna 
3. Ogni valore stringa è associato ad un numero in un 
Dictionary 
4. Sostituisco i valori stringa nella colonna con i numeri 
del Dictionary 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Dictionary encoding - 2 livello 
Creo il 
dizionario 
DISTINCT 
Indice Quarter 
1 Q1 
2 Q2 
3 Q3 
4 Q4 
SOSTITUISCI 
Conoscendo i possibili valori della 
stringa utilizzo il numero minimo di 
bit per rappresentarla. In questo 
caso 4 possibili valori bastano 2 bit. 
Quarter 
Q1 
Q4 
Q1 
... 
Q2 
Q3 
Q1 
... 
Q3 
Q3 
Q2 
... 
Q1 
Q1 
.... 
Quarter 
1 
1 
1 
... 
2 
2 
2 
... 
3 
3 
3 
... 
4 
4 
.... 
RLE 
xVelocity storage 
Quarter Count Lunghezza 
1 1 400 
2 400 400 
3 800 100 
4 900 100 
Con il dictionary encoding Vertipaq è data typing 
independent. Non ha nessuna importanza il tipo dei campi 
che si utilizzano nelle viste per popolare il modello 
#sqlsatParma 
#sqlsat355 November 22nd, 2014 
Versione compressa 
Dizionario
Conclusioni su RLE e Dictionary encoding 
 Una stringa nella tabella (osceno) dei fatti non ha 
più nessun prezzo grazie al dictionary encoding 
 DOVETE vivere  pensando che Vertipaq memorizza i 
dati in questo modo. E’ fondamentale quando andrete a 
costruire un modello con Vertipaq 
 Importa solo il numero di valori distinti delle colonne 
 Tanti valori distinti occupano più spazio (+ RAM) 
ed più lungo fare analisi 
 Pochi valori distinti occupano poco spazio (- RAM) 
e tutte operazioni ridotte 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Conclusioni sulla compressione 
 Dictionary Encoding 
 Avviene quando è necessario: per una colonna con valori 
interi e con valori distinti molto alti conviene memorizzare il 
numero perché il dizionario sarebbe troppo grande 
 Rende le tabelle data type independent 
 RLE Encoding 
 Solo se i dati compressi sono più piccoli dell’originale 
 Dipende fortemente dall’ordine dei dati 
 SSAS sceglie il sorting migliore durante il process (10 s/milione di 
righe). Trovare stesso ordinamento per le colonne è difficile. 
Thomas Kejser: + 25% compressione con ordinamento sorgente 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Conclusioni sulla compressione 
 La compressione deriva dal fatto che abbiamo: 
 Column Store 
 Dictionary Encoding 
 RLE Encoding 
 Compressione: uso meno RAM e quindi più velocità e il 
modello riesce a stare nel server . Scansioni delle 
colonne sono più veloci 
 Il valore di compressione che ci possiamo aspettare è…. 
 Non lo sa nessuno ma la risposta commerciale è 10x 
anche si può arrivare a 50x o a 2x 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Segmentation 
 Fino ad ora abbiamo visto come Vertipaq processa e 
comprime una colonna 
 Cosa succede con la tabella intera? 
 In realtà Vertipaq non processa tutta la tabella prima di 
fare la compressione perché non avrebbe abbastanza 
memoria 
 Si usa la tecnica della segmentation 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Segmentation 
 Ogni tabella è divisa in segmenti (dimensione variabile) 
 8 milioni di righe per ogni segmento in SSAS 
 1 milione di righe in PowerPivot 
 C’è un dizionario globale per la tabella 
 Bit-sizing (forma compatta del dizionario) è locale ad 
ogni segmento 
 Ci sono delle DMV per avere informazione sui segmenti 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Segmentation cycle 
Legge il segmento 
Genera o aggiorna il dizionario 
globale 
Genera un dizionario locale al 
segmento bit-sizing 
Comprime tutto e memorizza e 
passa al secondo segmento 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Importanza della Segmentation 
 Viene usata per lavorare su un insieme ridotto di dati per la 
compressione ( 1 o 8 millioni di righe) 
 Viene usata come base per il parallelismo all’interno delle 
query 
 Quando Vertipaq risolve una query usa un thread per 
ogni segmento della tabella (per fare la scansione) 
 Se ho meno di 8 milioni userà un solo thread perché è 
antipoduttivo usarne di più 
 Se ho 80 milioni di righe userà 10 thread su 10 core 
separati (ideale ma impensabile per conflitto sul bus) 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Segmentation 
 Fasi della segmentazione durante il processing 
Legge e crea i 
dizionari del segmento 
N 
Legge e crea i 
dizionari del segmento 
N + 1 
Comprime 
segmento N 
Comprime 
segmento N+1 
Crea colonne calcolate, 
gerarchie, relazioni e 
tutte le strutture dati 
Fine lettura dati del 
modello 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Segmentation: caso speciale del 3 segmento 
 Vertipaq cerca di ridurre il numero di segmenti da caricare 
 fa un tentativo di leggere i primi due segmenti assieme (come 
fosse unico). Se ci sono 12 milioni di righe è inutile leggerli in due 
passi e legge direttamente 16 milioni di righe (primo segmento) 
altrimenti segmenta normalmente 
Legge e crea i 
dizionari del 
segmento 1 e 2 
Legge e crea i 
dizionari del segmento 
3 
Comprime 
segmento 1 
Comprime 
segmento 2 
Crea colonne calcolate, 
gerarchie, relazioni e 
tutte le strutture dati 
Comprime 
segmento 3 
Fine lettura dati del 
modello 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Configurazione della segmentazione 
 La configurazione e a livello di istanza 
 DefaultSegmentRowCount (0 = default) 
 ProcessingTimeboxSecPerMRow per decidere il tempo entro al 
quale deve ordinare 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Uso memoria durante il processing 
 Ogni tabella è processata sequenzialmente (anche se 
partizionata) 
 Non ci sono parallelismi sulla partizione come SSAS 
 Ogni tabella è divisa in segmenti 
 Per ogni segmento 
 Caricamento 
 Compressione (un thread per colonna: parallelismo) 
 Memorizzazione 
 Più tabelle possono essere caricate in parallelo 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Uso memoria durante memorizzazione 
 L’uso della memoria nella memorizzazione dipende da: 
 Numero di colonne 
 Cardinalità di ogni colonna (valori distinct) 
 Tipo di dato (varia il dizionario) 
 Numero di righe 
 Non ci sono formule per calcolare lo spazio occupato da 
una tabella. L’unico modo è creare un prototipo!!! 
 Attenzione ad avere un prototipo con dati veri  i dati 
nascosti sfalsano la distribuzione dei dati. 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Uso memoria durante le query 
 La cache richiede memoria 
 Le query semplici richiedono un po’ di memoria 
 Le query complesse richiedono molta memoria 
 Fare spooling per valori temporanei 
 Materializzare un dataset ( se faccio una query su più 
colonne alla fine devo unire i risultati ) 
 Problema: in quanto molte volte può capitare che 
la versione materializzata sia più grande della 
tabella originale 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Materialization 
 Se vogliamo eseguire su un database colonnare la 
seguente query: 
SELECT SUM(num730) AS N730,[COD_Ufficio] 
FROM [dbo].[Dichiarazioni730] 
WHERE [COD_Utente] = 345 AND [Tipo730] = 1 
GROUP BY [COD_Ufficio] 
Tipo730 
1 
2 
1 
1 
Cod_Ufficio 
4555 
2345 
6545 
444 
COD_Utente 
345 
1678 
345 
100 
 Ci sono diverse tecniche ma agli estremi ci sono: 
 Early Materialization 
 Late Materializzation 
num730 
234 
100 
400 
3 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Early materialization 
Tipo730 
1 
2 
1 
1 
Cod_Ufficio 
4555 
2345 
4555 
444 
num730 
234 
100 
400 
3 
COD_Utente 
345 
1678 
345 
100 
Ricomponiamo il row store 
(Materializzo) 
345 1 4555 234 
1678 2 2345 100 
345 1 4555 400 
100 1 444 3 
SELECT SUM(num730) AS N730,[COD_Ufficio] 
FROM [dbo].[Dichiarazioni730] 
WHERE [COD_Utente] = 345 AND [Tipo730] = 1 
GROUP BY [COD_Ufficio] 
La fregatura è che faccio tanto 
lavoro per comprimere in 
colonne separate e poi devo 
riunire tutto. Uso tanta 
memoria se faccio select * 
Applico la where 
345 1 4555 234 
345 1 4555 400 
Proiezione per num730 e cod_ufficio 
4555 234 
4555 400 
Sommo 
4555 634 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Late materializzation 
Tipo730 
Tipo730 
1 
2 
1 
1 
Cod_Ufficio 
4555 
2345 
4555 
444 
num730 
234 
100 
400 
3 
COD_COD_Utente 
345 
1678 
345 
100 
SELECT SUM(num730) AS N730,[COD_Ufficio] 
FROM [dbo].[Dichiarazioni730] 
WHERE [COD_Utente] = 345 AND [Tipo730] = 1 
GROUP BY [COD_Ufficio] 
Bitmap 
1 
0 
1 
0 
Applico la clausola 
where sulle due 
colonne separate 
Materializzo 
4555 234 
4555 400 
Sommo 
4555 634 
Bitmap 
1 
0 
1 
1 
And 
Bitmap 
1 
0 
1 
0 
Cod_Ufficio 
4555 
2345 
6545 
444 
num730 
234 
100 
400 
3 
Applico la bitmap 
Cod_Ufficio 
4555 
4555 
num730 
234 
400 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Quando avviene la materializzazione 
 La materializzazione avviene per Join complessi 
 La materializzazione avviene per iterazioni complesse 
 Durante il salvataggio di dati temporanei 
Praticamente devo sempre materializzare 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Quanto spazio uso per il mio modello? 
 Nella directory dei dati, c’è un folder per ogni database 
 ..Microsoft SQL ServerMSAS11.MSSQLSERVEROLAPData 
 AdventureWorks Tabular Model SQL 2012....... 
 Tipo di file ed estensioni 
 Dictionary: .DICTIONARY 
 Data: .IDF 
 Index: .IDF (POS_TO_ID, ID_TO_POS) 
 Relationship: GUID + .HDX 
 Hierachies: .JDF 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Quanto spazio uso per il mio modello? 
 Ci sono anche delle DMV per estrarre le informazioni sullo 
stato del database di Tabular (ma sono complicate) 
 Ritorna tutte le possibili DMV 
 SELECT * FROM $SYSTEM.DISCOVER_SCHEMA_ROWSETS 
 Ritorna la memoria utilizzata da tutti gli oggetti 
 SELECT * FROM $SYSTEM.DISCOVER_OBJECT_MEMORY_USAGE 
 Dettagli delle singole colonne 
 SELECT * FROM $SYSTEM.DISCOVER_STORAGE_TABLE_COLUMNS 
 Dettagli sui segmenti 
 SELECT * FROM 
$SYSTEM.DISCOVER_STORAGE_TABLE_COLUMN_SEGMENT 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Quanto spazio uso per il mio modello? 
 In alternativa alle DMV usate il PowerPivot di Kasper De 
Jonge. 
 Si apre un foglio excel in cui da powerpivot interrogo le 
DMV su un istanza di analisys services 
http://www.powerpivotblog.nl/what-is-using-all-that-memory-on- 
my-analysis-server-instance/ 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Best Practice (ridurre il dictionary) 
 Ridurre la lunghezza delle stringhe 
 Ridurre il numero di valori distinti 
 Dividere DateTime in due colonne (troppi valori distinti) 
 Date 
 Time 
 Deve essere fissata una precisione per i valori floating point 
 76.201 diventa 76.2 
 Cercate di risolvere tutto a livello di sorgente dati e non in 
colonne calcolate (esempio con le viste) 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Best Practice (ridurre dimensioni tabelle) 
 Attenzione alle Junk Dimensions. Faccio la cross join 
della distinct di questi valori junk e li metto nella tabella 
junk e poi ci punto dentro con un intero 
 Meglio + campi con pochi valori distinti sulla tabella 
dei fatti che uno che è il cross join dei valori distinti 
 Se poi ho dimensioni con solo Id e descrizione è 
meglio memorizzare la descrizione nei fatti 
 Descrizione occupa come l’Id nei fatti 
 Non pago un join a query time 
 Ho un tabella in meno da memorizzare che è inutile 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Best Practice (ridurre dimensioni tabelle) 
 Evitare risultati parziali in colonne calcolate 
 essi tendono ad avere molti valori distinti 
 aumentano il numero di colonne 
 Rimuovere le colonne non utilizzate 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Best Practice dimensioni degeneri 
 Problema -> Memorizzare un ID per il DrillThrought nei 
report è costoso (sacco di valori distinti) 
 Un solo valore per ogni riga 
 un grande dizionario per grandi tabelle 
 Soluzione -> Splittare in più colonne 
 Tabella di 100 milioni di righe. N° di fattura che è 
dato da anno + progressivo. Lo divido in due o più 
colonne. Le colonne hanno un dizionario più piccolo. 
 Se poi lo devo visualizzare sul report rimaterializzare 
lo faccio su un sottoinsieme di righe . 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Workbook Optimizer 
 esamina la composizione del modello di dati 
all'interno della vostra cartella di lavoro di 
PowerPivot 
http://www.microsoft.com/en-us/download/details.aspx?id=38793 
 vede se i dati in essa contenuti possono 
occupare meno spazio 
 vede se possibile fare una migliore 
compressione 
 Non è il massimo deve migliorare molto 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
Conclusioni su xVelocity 
 Ha degli algoritmi di compressione molto efficienti 
 Molto veloce sulle colonne singole 
 L’accesso a più colonne richiede la materializzazione 
 Metodo di memorizzazione diverso dai classici 
database 
 Richiede un cambiamento di mentalità 
 Tentate di pensare a colonne singole 
 Tutte queste caratteristiche si riflettono in DAX. 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
DEMO 
 Testiamo tutto quello fino a qui imparato su un 
caso reale di foglio excel bello grande. 
#sqlsatParma 
#sqlsat355 November 22nd, 2014
THANKS! 
#sqlsatParma 
#sqlsat355 
#sqlsatParma 
#sqlsat355 November 22nd, 2014

xVelocity in Deep

  • 1.
    xVelocity in Deep Marco Pozzan twitter: @marcopozzan email: info@marcopozzan.it site: www.marcopozzan.it #sqlsatParma #sqlsat355 November 22nd, 2014
  • 2.
  • 3.
  • 4.
    Speaker info MVP SQL Server  Presidente della community 1nn0va (www.innovazionefvg.net)  Project manager del reparto Business Intelligence presso CGN S.P.A. (www.cgn.it)  Docente ITS all’Università di Pordenone  Partecipo agli eventi community #sqlsatParma #sqlsat355 November 22nd, 2014
  • 5.
    Agenda  Gestionedelle query  Che cosa è xVelocity in-memory  Row vs Columnar storage  RLE e Dictionary Encoding  Uso memoria: memorizzazione, processing e query  Best practice #sqlsatParma #sqlsat355 November 22nd, 2014
  • 6.
    Gestione delle query  Direct Query mode  Trasformazione da DAX a SQL  Query sul motore SQL Server  Molte limitazioni (solo connessione SQL, solo DAX no MDX, limiti DAX, no colonne calcolate, no security)  In Memory mode  Engine per elaborare formule DAX (formula engine DAX)  Storage Engine Vertipaq (xVelocity in-memory)  Sfrutta tutte le funzionalità di Tabular #sqlsatParma #sqlsat355 November 22nd, 2014
  • 7.
    Gestione delle query DAX/MDX query Analysis Services 2012 Tabular Model DirectQuery Mode (Motore di query) In-Memory Mode (Motore di query) SQL Query Query Query Storage engine query Storage engine query Storage engine query  PROCESS = Lettura dalla sorgente dati  Vertipaq contiene il risultato del processing del database External Data Sources Process Vertipaq Storage #sqlsatParma #sqlsat355 November 22nd, 2014
  • 8.
    Che cosa èxVelocity in-memory?  E’ un database in memoria (dati sono in memoria)  E’ basato su una metodologia relazionale  Database colonnare #sqlsatParma #sqlsat355 November 22nd, 2014
  • 9.
    Come lavora unrow storage Alloco spazio su disco (pagine) Id FirstName LastName BirthDate Marital Status Children 1 Larry Gill 13/04/1977 00:00 M 1 2 Geoffrey Gonzalez 06/02/1977 00:00 S 2 3 Blake Collins 23/04/1975 00:00 M 0 4 Alexa Watson 25/08/1977 00:00 S 0 5 Jacquelyn Dominguez 27/09/1977 00:00 M 1 6 Casey Gutierrez 17/12/1977 00:00 M 1 7 Colleen Lu 17/07/1973 00:00 M 2 8 Jeremiah Stewart 26/06/1979 00:00 S 1 9 Leah Li 06/10/1976 00:00 S 0 Id FirstName LastName BirthDate Marital Status Children 1 Larry Gill 13/04/1977 00:00 M 1 2 Geoffrey Gonzalez 06/02/1977 00:00 S 2 3 Blake Collins 23/04/1975 00:00 M 0 4 Alexa Watson 25/08/1977 00:00 S 0 Alloco ancora spazio su disco perchè finito 5 Jacquelyn Dominguez 27/09/1977 00:00 M 1 6 Casey Gutierrez 17/12/1977 00:00 M 1 7 Colleen Lu 17/07/1973 00:00 M 2 8 Jeremiah Stewart 26/06/1979 00:00 S 1 9 Leah Li 06/10/1976 00:00 S 0 #sqlsatParma #sqlsat355 November 22nd, 2014
  • 10.
    Caratteristiche di unrow storage  SELECT * di una tabella  Legge tutta la tabella dalla prima all’ultima riga  SELECT SUM(children) della tabella  Legge tutta la tabella dalla prima all’ultima riga e poi si legge solo la colonna children per fare la somma  Prestazioni pessime per un dato piccolo devo fare tanto I/0 su disco che poi non serve #sqlsatParma #sqlsat355 November 22nd, 2014
  • 11.
    Caratteristiche di unrow storage  Il risultato della SELECT SUM(children) non cambia nemmeno se faccio I/O in memoria e non su disco  Trasferisco i dati dalla memoria alla cache della CPU dove si svolge il calcolo  La cache interna è molto limitata  Pessimo uso perché carico una grande parte di memoria per poi usarne un pezzettino  Ottengo comunque prestazioni peggiori rispetto al fatto di lavorare su dati più compatti (Problema) #sqlsatParma #sqlsat355 November 22nd, 2014
  • 12.
    Soluzione con gliindici  Se devo fare spesso la SUM(children)  Creo un indice su children  La query richiede solo il campo children (l’indice copre la query), leggo solo l’indice e non tutta la tabella  L’indice contiene dati più compatti e mi aiuta per I/O  Gli indici in generale riducono il numero di colonne di una tabella e ottimizzano l’I/0 Concetto di Column Storage #sqlsatParma #sqlsat355 November 22nd, 2014
  • 13.
    Caratteristiche di uncolumn storage  Portiamo il concetto di indice in memoria  Estremizziamo il concetto di indice Marital Status Id Id FirstName FirstName LastName BirthDate BirthDate Marital Status Children 1 1 Larry Larry Gill 13/13/04/04/1977 1977 00:00:00 00 M M 1 2 2 Geoffrey Geoffrey Gonzalez 06/06/02/02/1977 1977 00:00:00 00 S S 2 3 3 Blake Blake Collins 23/23/04/04/1975 1975 00:00:00 00 M M 0 4 4 Alexa Alexa Watson 25/25/08/08/1977 1977 00:00:00 00 S S 0 5 5 Jacquelyn Jacquelyn Dominguez 27/27/09/09/1977 1977 00:00:00 00 M M 1 6 6 Casey Casey Gutierrez 17/17/12/12/1977 1977 00:00:00 00 M M 1 7 7 Colleen Colleen Lu 17/17/07/07/1973 1973 00:00:00 00 M M 2 8 8 Jeremiah Jeremiah Stewart 26/26/06/06/1979 1979 00:00:00 00 S S 1 9 9 Leah Leah Li 06/06/10/10/1976 1976 00:00:00 00 S S 0 Un file per colonna #sqlsatParma #sqlsat355 November 22nd, 2014
  • 14.
    Caratteristiche di uncolumn storage  Faccio una SELECT SUM(children) della tabella  Non devo fare un indice  La colonna è già l’indice perché contiene solo children  Molto veloce  Faccio SELECT SUM(children) GROUP BY FirstName  Non è più così bello  Devo leggere due colonne: Children e FirstName  Devo poi unire il risultato pagando tempo di CPU #sqlsatParma #sqlsat355 November 22nd, 2014
  • 15.
    Caratteristiche di uncolumn storage  Rispetto alla row storage  più velocità se devo leggere una colonna  più velocità se leggo poche colonne  più lento se faccio SELECT * #sqlsatParma #sqlsat355 November 22nd, 2014
  • 16.
    Column vs Row  Memorizzazione su colonna  Accesso veloce ad una singola colonna  Ho la necessità di materializzare le righe  Spendiamo CPU per ridurre I/0 (le CPU le possono fare più veloci o metterne tante )  Memorizzazione per riga  Accesso veloce alla singola riga  Non necessita di materializzazione  Spendiamo l’I/O per ridurre la CPU (i dischi o la memoria non si possono fare più veloci ) #sqlsatParma #sqlsat355 November 22nd, 2014
  • 17.
    Cambiare il mododi pensare (colonnare)  Siamo in un mondo in cui lo storage è fatto da una sola colonna .  Ci sono cose che si possono fare memorizzando i dati in colonna che sono più efficienti rispetto ai dati memorizzati su riga Sapete come funziona la compressione di SQL Server?  per riga (non fa grandi cose… pulizie spazi bianchi, ridurre caratteri unicode, ridurre i decimali …..)  per pagina (identifica all’interno della pagina parti uguali e le indicizza per poi comprimere la pagina creando un indice all’inizio) #sqlsatParma #sqlsat355 November 22nd, 2014
  • 18.
    Compressione in Vertipaq  Vertipaq (simile compressione di pagina in SQL Server)  Identifica parti uguali nell’aria di memoria  Crea una struttura per rappresentare le parti uguali e ottiene la struttura compressa della colonna  Più efficiente di SQL perché si ragiona solo su una colonna con pochi valori distinti rispetto alla pagina di SQL in cui ho righe con più colonne e con meno valori distinti . Vediamo come Vertipaq esegue la compressione #sqlsatParma #sqlsat355 November 22nd, 2014
  • 19.
    Run Length Encoding(RLE) - 1 livello Children 1 1 1 1 1 ... 2 2 2 2 2 2 2 2 .... Children Inizio Lunghezza 1 1 200 2 201 400 FirstName Larry Larry Larry ... Geoffrey Geoffrey Geoffrey ... Alexa Alexa Alexa ... Colleen Colleen ... Potrei anche decidere di togliere la colonna inizio e tenere solo la fine FirstName Lunghezza Larry 400 Geoffrey 400 Alexa 100 Colleen 100 BirthDate 13/04/1977 13/05/1977 13/06/1977 .... 15/04/1980 16/04/1947 13/04/1976 ... 13/04/1976 13/04/1976 13/04/1976 ... 13/04/1990 13/04/1934 ... BirthDate lunghezza 13/04/1977 1 13/05/1977 1 13/06/1977 1 .... 15/04/1980 1 16/04/1947 1 13/04/1976 1 ... 13/04/1976 1 13/04/1976 1 13/04/1976 1 ... 13/04/1990 1 13/04/1934 1 ... Le date cambiano così di frequente che se provassi a comprimerla avrei su lunghezza tutti 1 e otterrei una tabella più grande dell’originale Vertipaq lascia l’originale. #sqlsatParma #sqlsat355 November 22nd, 2014
  • 20.
    Run Length Encoding(RLE) - 1 livello  Vertipaq non usa mai più memoria rispetto alla colonna sorgente…se non riesce a comprimerla la lascia come è  Vertipaq durante il processing di un tabella  Divide la tabella in colonne  Comprime ogni colonna con RLE  Attenzione!!! L’ordinamento delle colonne deve essere lo stesso per ogni colonna perchè devo materializzare i dati delle varie colonne (se ne occupa vertipaq ) buon ordinamento = buona compressione #sqlsatParma #sqlsat355 November 22nd, 2014
  • 21.
    Dictionary encoding -2 livello  Più importante di RLE  Vediamo i passi per creare il Dictionary 1. Vertipaq legge una colonna di tipo stringa 2. Effettua il distinct della colonna 3. Ogni valore stringa è associato ad un numero in un Dictionary 4. Sostituisco i valori stringa nella colonna con i numeri del Dictionary #sqlsatParma #sqlsat355 November 22nd, 2014
  • 22.
    Dictionary encoding -2 livello Creo il dizionario DISTINCT Indice Quarter 1 Q1 2 Q2 3 Q3 4 Q4 SOSTITUISCI Conoscendo i possibili valori della stringa utilizzo il numero minimo di bit per rappresentarla. In questo caso 4 possibili valori bastano 2 bit. Quarter Q1 Q4 Q1 ... Q2 Q3 Q1 ... Q3 Q3 Q2 ... Q1 Q1 .... Quarter 1 1 1 ... 2 2 2 ... 3 3 3 ... 4 4 .... RLE xVelocity storage Quarter Count Lunghezza 1 1 400 2 400 400 3 800 100 4 900 100 Con il dictionary encoding Vertipaq è data typing independent. Non ha nessuna importanza il tipo dei campi che si utilizzano nelle viste per popolare il modello #sqlsatParma #sqlsat355 November 22nd, 2014 Versione compressa Dizionario
  • 23.
    Conclusioni su RLEe Dictionary encoding  Una stringa nella tabella (osceno) dei fatti non ha più nessun prezzo grazie al dictionary encoding  DOVETE vivere  pensando che Vertipaq memorizza i dati in questo modo. E’ fondamentale quando andrete a costruire un modello con Vertipaq  Importa solo il numero di valori distinti delle colonne  Tanti valori distinti occupano più spazio (+ RAM) ed più lungo fare analisi  Pochi valori distinti occupano poco spazio (- RAM) e tutte operazioni ridotte #sqlsatParma #sqlsat355 November 22nd, 2014
  • 24.
    Conclusioni sulla compressione  Dictionary Encoding  Avviene quando è necessario: per una colonna con valori interi e con valori distinti molto alti conviene memorizzare il numero perché il dizionario sarebbe troppo grande  Rende le tabelle data type independent  RLE Encoding  Solo se i dati compressi sono più piccoli dell’originale  Dipende fortemente dall’ordine dei dati  SSAS sceglie il sorting migliore durante il process (10 s/milione di righe). Trovare stesso ordinamento per le colonne è difficile. Thomas Kejser: + 25% compressione con ordinamento sorgente #sqlsatParma #sqlsat355 November 22nd, 2014
  • 25.
    Conclusioni sulla compressione  La compressione deriva dal fatto che abbiamo:  Column Store  Dictionary Encoding  RLE Encoding  Compressione: uso meno RAM e quindi più velocità e il modello riesce a stare nel server . Scansioni delle colonne sono più veloci  Il valore di compressione che ci possiamo aspettare è….  Non lo sa nessuno ma la risposta commerciale è 10x anche si può arrivare a 50x o a 2x #sqlsatParma #sqlsat355 November 22nd, 2014
  • 26.
    Segmentation  Finoad ora abbiamo visto come Vertipaq processa e comprime una colonna  Cosa succede con la tabella intera?  In realtà Vertipaq non processa tutta la tabella prima di fare la compressione perché non avrebbe abbastanza memoria  Si usa la tecnica della segmentation #sqlsatParma #sqlsat355 November 22nd, 2014
  • 27.
    Segmentation  Ognitabella è divisa in segmenti (dimensione variabile)  8 milioni di righe per ogni segmento in SSAS  1 milione di righe in PowerPivot  C’è un dizionario globale per la tabella  Bit-sizing (forma compatta del dizionario) è locale ad ogni segmento  Ci sono delle DMV per avere informazione sui segmenti #sqlsatParma #sqlsat355 November 22nd, 2014
  • 28.
    Segmentation cycle Leggeil segmento Genera o aggiorna il dizionario globale Genera un dizionario locale al segmento bit-sizing Comprime tutto e memorizza e passa al secondo segmento #sqlsatParma #sqlsat355 November 22nd, 2014
  • 29.
    Importanza della Segmentation  Viene usata per lavorare su un insieme ridotto di dati per la compressione ( 1 o 8 millioni di righe)  Viene usata come base per il parallelismo all’interno delle query  Quando Vertipaq risolve una query usa un thread per ogni segmento della tabella (per fare la scansione)  Se ho meno di 8 milioni userà un solo thread perché è antipoduttivo usarne di più  Se ho 80 milioni di righe userà 10 thread su 10 core separati (ideale ma impensabile per conflitto sul bus) #sqlsatParma #sqlsat355 November 22nd, 2014
  • 30.
    Segmentation  Fasidella segmentazione durante il processing Legge e crea i dizionari del segmento N Legge e crea i dizionari del segmento N + 1 Comprime segmento N Comprime segmento N+1 Crea colonne calcolate, gerarchie, relazioni e tutte le strutture dati Fine lettura dati del modello #sqlsatParma #sqlsat355 November 22nd, 2014
  • 31.
    Segmentation: caso specialedel 3 segmento  Vertipaq cerca di ridurre il numero di segmenti da caricare  fa un tentativo di leggere i primi due segmenti assieme (come fosse unico). Se ci sono 12 milioni di righe è inutile leggerli in due passi e legge direttamente 16 milioni di righe (primo segmento) altrimenti segmenta normalmente Legge e crea i dizionari del segmento 1 e 2 Legge e crea i dizionari del segmento 3 Comprime segmento 1 Comprime segmento 2 Crea colonne calcolate, gerarchie, relazioni e tutte le strutture dati Comprime segmento 3 Fine lettura dati del modello #sqlsatParma #sqlsat355 November 22nd, 2014
  • 32.
    Configurazione della segmentazione  La configurazione e a livello di istanza  DefaultSegmentRowCount (0 = default)  ProcessingTimeboxSecPerMRow per decidere il tempo entro al quale deve ordinare #sqlsatParma #sqlsat355 November 22nd, 2014
  • 33.
    Uso memoria duranteil processing  Ogni tabella è processata sequenzialmente (anche se partizionata)  Non ci sono parallelismi sulla partizione come SSAS  Ogni tabella è divisa in segmenti  Per ogni segmento  Caricamento  Compressione (un thread per colonna: parallelismo)  Memorizzazione  Più tabelle possono essere caricate in parallelo #sqlsatParma #sqlsat355 November 22nd, 2014
  • 34.
    Uso memoria durantememorizzazione  L’uso della memoria nella memorizzazione dipende da:  Numero di colonne  Cardinalità di ogni colonna (valori distinct)  Tipo di dato (varia il dizionario)  Numero di righe  Non ci sono formule per calcolare lo spazio occupato da una tabella. L’unico modo è creare un prototipo!!!  Attenzione ad avere un prototipo con dati veri  i dati nascosti sfalsano la distribuzione dei dati. #sqlsatParma #sqlsat355 November 22nd, 2014
  • 35.
    Uso memoria durantele query  La cache richiede memoria  Le query semplici richiedono un po’ di memoria  Le query complesse richiedono molta memoria  Fare spooling per valori temporanei  Materializzare un dataset ( se faccio una query su più colonne alla fine devo unire i risultati )  Problema: in quanto molte volte può capitare che la versione materializzata sia più grande della tabella originale #sqlsatParma #sqlsat355 November 22nd, 2014
  • 36.
    Materialization  Sevogliamo eseguire su un database colonnare la seguente query: SELECT SUM(num730) AS N730,[COD_Ufficio] FROM [dbo].[Dichiarazioni730] WHERE [COD_Utente] = 345 AND [Tipo730] = 1 GROUP BY [COD_Ufficio] Tipo730 1 2 1 1 Cod_Ufficio 4555 2345 6545 444 COD_Utente 345 1678 345 100  Ci sono diverse tecniche ma agli estremi ci sono:  Early Materialization  Late Materializzation num730 234 100 400 3 #sqlsatParma #sqlsat355 November 22nd, 2014
  • 37.
    Early materialization Tipo730 1 2 1 1 Cod_Ufficio 4555 2345 4555 444 num730 234 100 400 3 COD_Utente 345 1678 345 100 Ricomponiamo il row store (Materializzo) 345 1 4555 234 1678 2 2345 100 345 1 4555 400 100 1 444 3 SELECT SUM(num730) AS N730,[COD_Ufficio] FROM [dbo].[Dichiarazioni730] WHERE [COD_Utente] = 345 AND [Tipo730] = 1 GROUP BY [COD_Ufficio] La fregatura è che faccio tanto lavoro per comprimere in colonne separate e poi devo riunire tutto. Uso tanta memoria se faccio select * Applico la where 345 1 4555 234 345 1 4555 400 Proiezione per num730 e cod_ufficio 4555 234 4555 400 Sommo 4555 634 #sqlsatParma #sqlsat355 November 22nd, 2014
  • 38.
    Late materializzation Tipo730 Tipo730 1 2 1 1 Cod_Ufficio 4555 2345 4555 444 num730 234 100 400 3 COD_COD_Utente 345 1678 345 100 SELECT SUM(num730) AS N730,[COD_Ufficio] FROM [dbo].[Dichiarazioni730] WHERE [COD_Utente] = 345 AND [Tipo730] = 1 GROUP BY [COD_Ufficio] Bitmap 1 0 1 0 Applico la clausola where sulle due colonne separate Materializzo 4555 234 4555 400 Sommo 4555 634 Bitmap 1 0 1 1 And Bitmap 1 0 1 0 Cod_Ufficio 4555 2345 6545 444 num730 234 100 400 3 Applico la bitmap Cod_Ufficio 4555 4555 num730 234 400 #sqlsatParma #sqlsat355 November 22nd, 2014
  • 39.
    Quando avviene lamaterializzazione  La materializzazione avviene per Join complessi  La materializzazione avviene per iterazioni complesse  Durante il salvataggio di dati temporanei Praticamente devo sempre materializzare #sqlsatParma #sqlsat355 November 22nd, 2014
  • 40.
    Quanto spazio usoper il mio modello?  Nella directory dei dati, c’è un folder per ogni database  ..Microsoft SQL ServerMSAS11.MSSQLSERVEROLAPData  AdventureWorks Tabular Model SQL 2012.......  Tipo di file ed estensioni  Dictionary: .DICTIONARY  Data: .IDF  Index: .IDF (POS_TO_ID, ID_TO_POS)  Relationship: GUID + .HDX  Hierachies: .JDF #sqlsatParma #sqlsat355 November 22nd, 2014
  • 41.
    Quanto spazio usoper il mio modello?  Ci sono anche delle DMV per estrarre le informazioni sullo stato del database di Tabular (ma sono complicate)  Ritorna tutte le possibili DMV  SELECT * FROM $SYSTEM.DISCOVER_SCHEMA_ROWSETS  Ritorna la memoria utilizzata da tutti gli oggetti  SELECT * FROM $SYSTEM.DISCOVER_OBJECT_MEMORY_USAGE  Dettagli delle singole colonne  SELECT * FROM $SYSTEM.DISCOVER_STORAGE_TABLE_COLUMNS  Dettagli sui segmenti  SELECT * FROM $SYSTEM.DISCOVER_STORAGE_TABLE_COLUMN_SEGMENT #sqlsatParma #sqlsat355 November 22nd, 2014
  • 42.
    Quanto spazio usoper il mio modello?  In alternativa alle DMV usate il PowerPivot di Kasper De Jonge.  Si apre un foglio excel in cui da powerpivot interrogo le DMV su un istanza di analisys services http://www.powerpivotblog.nl/what-is-using-all-that-memory-on- my-analysis-server-instance/ #sqlsatParma #sqlsat355 November 22nd, 2014
  • 43.
    Best Practice (ridurreil dictionary)  Ridurre la lunghezza delle stringhe  Ridurre il numero di valori distinti  Dividere DateTime in due colonne (troppi valori distinti)  Date  Time  Deve essere fissata una precisione per i valori floating point  76.201 diventa 76.2  Cercate di risolvere tutto a livello di sorgente dati e non in colonne calcolate (esempio con le viste) #sqlsatParma #sqlsat355 November 22nd, 2014
  • 44.
    Best Practice (ridurredimensioni tabelle)  Attenzione alle Junk Dimensions. Faccio la cross join della distinct di questi valori junk e li metto nella tabella junk e poi ci punto dentro con un intero  Meglio + campi con pochi valori distinti sulla tabella dei fatti che uno che è il cross join dei valori distinti  Se poi ho dimensioni con solo Id e descrizione è meglio memorizzare la descrizione nei fatti  Descrizione occupa come l’Id nei fatti  Non pago un join a query time  Ho un tabella in meno da memorizzare che è inutile #sqlsatParma #sqlsat355 November 22nd, 2014
  • 45.
    Best Practice (ridurredimensioni tabelle)  Evitare risultati parziali in colonne calcolate  essi tendono ad avere molti valori distinti  aumentano il numero di colonne  Rimuovere le colonne non utilizzate #sqlsatParma #sqlsat355 November 22nd, 2014
  • 46.
    Best Practice dimensionidegeneri  Problema -> Memorizzare un ID per il DrillThrought nei report è costoso (sacco di valori distinti)  Un solo valore per ogni riga  un grande dizionario per grandi tabelle  Soluzione -> Splittare in più colonne  Tabella di 100 milioni di righe. N° di fattura che è dato da anno + progressivo. Lo divido in due o più colonne. Le colonne hanno un dizionario più piccolo.  Se poi lo devo visualizzare sul report rimaterializzare lo faccio su un sottoinsieme di righe . #sqlsatParma #sqlsat355 November 22nd, 2014
  • 47.
    Workbook Optimizer esamina la composizione del modello di dati all'interno della vostra cartella di lavoro di PowerPivot http://www.microsoft.com/en-us/download/details.aspx?id=38793  vede se i dati in essa contenuti possono occupare meno spazio  vede se possibile fare una migliore compressione  Non è il massimo deve migliorare molto #sqlsatParma #sqlsat355 November 22nd, 2014
  • 48.
    Conclusioni su xVelocity  Ha degli algoritmi di compressione molto efficienti  Molto veloce sulle colonne singole  L’accesso a più colonne richiede la materializzazione  Metodo di memorizzazione diverso dai classici database  Richiede un cambiamento di mentalità  Tentate di pensare a colonne singole  Tutte queste caratteristiche si riflettono in DAX. #sqlsatParma #sqlsat355 November 22nd, 2014
  • 49.
    DEMO  Testiamotutto quello fino a qui imparato su un caso reale di foglio excel bello grande. #sqlsatParma #sqlsat355 November 22nd, 2014
  • 50.
    THANKS! #sqlsatParma #sqlsat355 #sqlsatParma #sqlsat355 November 22nd, 2014