Passa al contenuto principale
Prodotto

Sfatare i miti sulla migrazione SQL: come le nuove funzionalità SQL semplificano il lift-and-shift verso il Lakehouse

Una guida dettagliata riga per riga sul passaggio di una stored procedure legacy a Databricks. Cursori, tabelle temporanee e transazioni multi-istruzione vengono migrati come SQL nell'ambito della migrazione del data warehouse.

di Abhishek Dey e Laurent Léturgez

  • Il cursore risiede nella procedura pianificata per l'esecuzione ogni notte. La tabella temporanea che nessuno ha documentato. La transazione che raggruppa tre aggiornamenti ed esegue il rollback se uno qualsiasi di essi fallisce. Tutto questo viene migrato ora, riga per riga.
  • Traduci la procedura. Non la riscrivi. PL/SQL si mappa su Databricks SQL Scripting pezzo per pezzo, stessa logica di business, stesso flusso di controllo, stesso team SQL.
  • La procedura finisce in Unity Catalog con lineage e controllo degli accessi. Una governance che lo schema originale non ha mai avuto.

Da qualche parte nel vostro data warehouse, centinaia di stored procedure si attivano ogni notte e, silenziosamente, mantengono attiva l'azienda. Sono state scritte anni fa da un gruppo di sviluppatori SQL che hanno ormai lasciato l'azienda da tempo. Hanno cursori annidati. Creano tabelle temporanee al volo. Raggruppano gli aggiornamenti su più tabelle in una singola transazione. E intorno alla riga 47, c'è un commento che dice semplicemente: “Non toccare questo.” Nessuno capisce più a fondo queste procedure. Eppure, tutti dipendono da esse. La dashboard dei ricavi, la chiusura finanziaria, il report delle operazioni: tutti, in un modo o nell'altro, riconducono a questi livelli di logica di business SQL procedurale.

Spostare i dati nel lakehouse è un processo ormai consolidato. L'ostacolo principale è sempre stato il nucleo procedurale di qualsiasi migrazione di data warehouse: le stored procedure, la gestione delle transazioni, le tabelle temporanee, il flusso di controllo e il fatto che gran parte dell'azienda si affidi ancora a competenze SQL. Ogni volta che si prospettava una migrazione, queste procedure erano la prima cosa che tutti indicavano: “Non possiamo migrare finché non riusciremo a eseguirle con modifiche minime. La nostra azienda è ancora fortemente basata su SQL.”

Abbiamo quindi deciso di prendere un caso d'uso simile a quello a cui probabilmente state pensando in questo momento, una procedura composita che abbiamo riscontrato in diverse migrazioni, e di mostrarlo, passo dopo passo, sul Lakehouse. Questo esempio si basa su un caso d'uso di migrazione da Oracle, ma può essere applicato a qualsiasi data warehouse (legacy o basato su cloud). 

Partiamo dalla logica di business originale

Questa procedura di esempio elabora gli ordini giornalieri. Esegue lo staging degli ordini non elaborati in una tabella temporanea, li convalida rispetto all'anagrafica clienti, esegue un ciclo sugli errori per registrare singolarmente ogni rifiuto, quindi aggiorna i riepiloghi dei ricavi regionali e contrassegna tutti gli ordini come elaborati, il tutto all'interno di una transazione che esegue il rollback in caso di errore.

Un unico job notturno che non deve assolutamente interrompersi.

In passato, migrare questa procedura significava riscriverla interamente in Python e Spark. Settimane di lavoro, nuovi bug da scovare e un team SQL che non era più in grado di gestire la propria logica di business.

Non l'abbiamo riscritta. L'abbiamo tradotta.

Ora gettiamo le basi su Databricks

Ogni procedura inizia con una firma e una rete di sicurezza. Il sistema legacy racchiudeva il corpo in BEGIN ... EXCEPTION ... END. Databricks utilizza invece DECLARE EXIT HANDLER FOR SQLEXCEPTION; stessa idea, sintassi leggermente diversa. Ipotizziamo che il catalogo e lo schema appropriati siano già stati impostati nella sessione.

La grande differenza non sta nel codice, ma in ciò che accade dopo il deployment. Su Databricks, la procedura viene registrata in Unity Catalog. Ottiene controlli di accesso, derivazione dei dati (lineage) a livello di colonna e rilevabilità in ogni workspace. Nel sistema attuale, risiedeva in uno schema di cui solo tre persone conoscevano la password.

Legacy

Databricks

CREATE OR REPLACE PROCEDURE name IS

CREATE OR REPLACE PROCEDURE [IF NOT EXISTS] <catalog>.<schema>.<procedure_name> ( [ procedure_parameter [, ...] ] )

   [ characteristic [...] ]

LANGUAGE SQL 

SQL SECURITY { INVOKER | DEFINER }

AS BEGIN

v_id NUMBER; prima di BEGIN

DECLARE v_id INT; all'interno di BEGIN

EXCEPTION WHEN OTHERS THEN

DECLARE EXIT HANDLER FOR SQLEXCEPTION

Riferimento: docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-ddl-create-procedure

Poi abbiamo affrontato le tabelle temporanee: una vittoria facile nella migrazione di un data warehouse

La procedura originale crea due tabelle temporanee per lo staging e gli errori di validazione. Rappresentano lo spazio di lavoro temporaneo da cui dipende il resto della logica.

Su Databricks, questa diventa una delle parti più semplici della migrazione. Nessun EXECUTE IMMEDIATE. Nessun ON COMMIT PRESERVE ROWS. La direttiva CREATE TEMP TABLE con ambito sessione è la sostituzione diretta, con un piccolo avvertimento: CREATE OR REPLACE TEMP TABLE non è ancora supportata, quindi esegui prima un drop se hai bisogno di rieseguire lo script nella stessa sessione.

Riferimento: docs.databricks.com/aws/en/tables/temporary-tables

Il cursore era la parte difficile — o almeno così pensavamo

Questo era il pezzo che tutti pensavano avrebbe richiesto una riscrittura. La procedura originale scorre gli errori di validazione uno ad uno, rifiuta ogni ordine non valido e ne registra il motivo. Un classico pattern a cursore. Decenni di memoria muscolare legacy (Oracle, ad esempio).

Lo scripting SQL di Databricks supporta i cursori in modo nativo, OPEN, FETCH e CLOSE a partire da Runtime 18.1. L'attributo %NOTFOUND diventa un CONTINUE HANDLER FOR NOT FOUNDLe etichette dei cicli e LEAVE sostituiscono EXIT WHEN.

La logica di scripting non ha rappresentato un problema

Il controllo condizionale (se non ci sono righe da elaborare, salta e registra) è rimasto quasi identico. SELECT ... INTO diventa SET var = (SELECT ...)Tutto il resto è identico.

Il nostro scripting SQL supporta l'intero toolkit procedurale: IF/ELSE, WHILE, FOR, LOOP, REPEAT, LEAVE, ITERATE, SIGNAL/RESIGNAL. Se la tua codebase contiene script Teradata BTEQ con direttive .GOTO e .LABEL , queste si mappano su cicli etichettati utilizzando LEAVE and ITERATE.

Riferimento: docs.databricks.com/aws/en/sql/language-manual/sql-ref-scripting

La transazione è stata il momento della svolta

Questo era l'ultimo tassello, quello che ha reso la migrazione effettivamente fattibile. La procedura originale aggiorna regional_revenue, contrassegna gli ordini come elaborati e registra il batch. Se una qualsiasi parte fallisce, viene eseguito il rollback di tutto.

Sul sistema legacy, si tratta di una transazione implicita con un COMMIT esplicito. Su Databricks, BEGIN ATOMIC ... END offre la stessa semantica, commit automatico in caso di successo, rollback automatico in caso di errore, con un vantaggio significativo: il rilevamento dei conflitti a livello di riga. I batch simultanei che scrivono sulla stessa tabella entrano in conflitto solo se interessano le stesse righe. Ad esempio, sia Oracle che Snowflake utilizzano il blocco a livello di tabella, il che forza l'esecuzione seriale.

L'istruzione MERGE può essere migrata su Databricks così com'è. Il COMMIT esplicito è scomparso poiché viene gestito da BEGIN ATOMIC. E il team ha smesso di preoccuparsi che i job batch simultanei si ostacolassero a vicenda.

Due note pratiche quando si adotta questo pattern:

  • Ogni tabella definita all'interno di un blocco atomico deve avere la funzionalità di tabella catalogManaged abilitata. Puoi abilitarla direttamente sulle tabelle Delta esistenti: ALTER TABLE <name> SET TBLPROPERTIES('delta.feature.catalogManaged'= 'supported');
  • BEGIN ATOMIC deve trovarsi al livello principale — in uno script SQL, in una cella di un notebook o in un task di un job SQL. 

Riferimento: docs.databricks.com/aws/en/transactions/

La procedura migrata completa

Stessa logica di business. Stesso flusso di controllo. Gestito da Unity Catalog. 

Per eseguirlo all'interno di una transazione, racchiudi la chiamata:

Cosa abbiamo imparato

Le tempistiche di migrazione per questi programmi possono essere ridotte del 50-75%, anche per stored procedure complesse con pesanti dipendenze da pacchetti PL/SQL. Questa efficienza deriva da un processo di traduzione meccanica che preserva la logica di business originale, garantendo che il team SQL possa continuare senza problemi il proprio lavoro di manutenzione. Oltre alla migrazione stessa, i team ottengono un nuovo potente vantaggio: una piattaforma unificata in cui gli stessi dati governati alimentano le loro dashboard, i modelli di machine learning e le iniziative di AI.

L'unico modo per sapere se le tue procedure vengono tradotte correttamente è provarne una. Scegli la stored procedure più piccola del tuo batch, preferibilmente una che nessuno ama sottoporre a debug. Crea un progetto di migrazione nel tuo workspace e inizia a usare Agentic Code Convertor!

(Questo post sul blog è stato tradotto utilizzando strumenti basati sull'intelligenza artificiale) Post originale

Ricevi gli ultimi articoli nella tua casella di posta

Iscriviti al nostro blog e ricevi gli ultimi articoli direttamente nella tua casella di posta.