Dapper: Eseguire BULK Insert

Durante il mese di luglio mi sono trovato a migrare un Azure Data Factory in Azure Function per una serie di motivazioni che non scrivero’ in questo momento. Il punto critico di tutto questo sviluppo e’ stato l’inserimento massivo dei dati dentro SQL Server. Certo, con ADF ed il Copy Data il gioco era semplicissimo a prescindere dalla quantita’ di dati. Via codice come mi comporto?

Dapper & BreakEvenPoint

Prima di entrare nel vivo del contenuto vorrei rimandare ad un mio post scritto su Linkedin dal titolo Rompere il codice - Quale sarà il #BreakEvenPoint? proprio in occasione di questo sviluppo

🚒 Rompere il codice

🤔 Quale sarà il #BreakEvenPoint?

Nel corso di questa settimana mi sono dedicato ad uno sviluppo interessante migrando un processo #AzureDataFactory in #AzureFunctions.

🍾 La riscrittura del processo -dal punto di vista teorico- era semplice. Lato pratico avevo un collo di bottiglia ben noto anche prima di scrivere il codice. #DataFactory ha una capacità di gestire spostamenti di dati tra diversi datasource infinitamente superiore rispetto al codice.

Per aggirare il problema ho deciso di effettuare una INSERT massiva utilizzando #dapper ed ero emozionato in quanto non mi ricordo l’ultima volta che mi era capitato di farlo.

❓ Come sono andati i test?

Andiamo per punti, cercando di includere anche quelli scontati.

🔴 Semaforo rosso sul confronto Dapper/ ADF, ma questo lo sapevo. Essendo tutto #async non mi preoccupo

🟢 Ottimi risultati nella INSERT massiva aumentando i dati del 33% rispetto al carico degli ultimi 12 mesi

🟠 Il punto di rottura l’ho trovato alzando i dati oltre 40%. Perche’ semaforo arancio? Ho ben chiaro dove intervenire e come se dovesse servire.

A cosa serve il post? Ricordatevi che quando fate #backend le #performance vanno considerate ed anche il margine di respiro! Ecco perche’ cercare il BEP!

A distanza di circa tre mesi sono piu’ che soddisfatto di questo sviluppo. Ho visto reggere carichi pari ad un x4 rispetto allo stimato senza dare grossi problemi.

Dapper & BulkInsert

Ora non voglio farvi perdere molto altro tempo ed ecco il codice sorgente per effettuare l’inserimento massivo tramite Dapper.

1
2
3
4
5
6
7
8
internal async Task<int> InsertAsync<T>(SqlConnection connection, List<T> items)
{
    string sql = GetQuery( ... );

    var result = await connection.ExecuteAsync(sql, items);

    return result;
}

Vi state chiedendo: come, tutto qua? Si! Certo, ci sono delle piccole note a cui are attenzione.

Punti d’attenzione

Il codice mostrato sopra non e’ funzionante al 100% per come l’ho scritto. Come avrete notato e’ presente GetQuery e questo non posso prevederlo io per voi. Mi spiego meglio. Passando T per identificare il tipo sara’ diversa anche la tabella su SQL Server.

All’interno di GetQuery dovrete capire a cosa corrisponde T e di conseguenza fare tornare la stringa SQL adatta.

Tips

Prima di chiudere vorrei darvi una serie di punti interessanti da tenere in considerazione durante lo sviluppo

  • I nomi delle colonne ed i campi presenti nel DTO devono essere gli stessi
  • Il DTO puo’ non contenere campi col valore di DEFAULT nella tabella in SQL Server
  • Eventuali modifiche strutturali alla tabella vanno poi verificate coi DTO relativi

Personalmente -durante il mio sviluppo- ho omesso delle colonne per i seguenti motivi

  • Primary Key: Ho utilizzato come chiave una NEWSEQUENTIALID -vedi SQL Server: NEWID versus NEWSEQUENTIALID- delegando il tutto al database in modo da farmi ringraziare anche dalle performance e relativi Index.

  • CreatedOn: Delegato il tutto al GETDATE()

  • Campi ALLOW NULL di interesse successivo

Ora -se volete- non vi resta che fare delle prove/ simulazioni a piacere coi vostri dati. Siete pronti a scoprire quale sara’ il Break Even Point del vostro codice?