Colonne generate da Delta Lake

Importante

Questa funzionalità è disponibile in anteprima pubblica.

Delta Lake supporta colonne generate che sono un tipo speciale di colonna i cui valori vengono generati automaticamente in base a una funzione specificata dall'utente su altre colonne della tabella Delta. Quando si scrive in una tabella con colonne generate e non si specificano in modo esplicito i valori, Delta Lake calcola automaticamente i valori. Ad esempio, è possibile generare automaticamente una colonna data (per partizionare la tabella per data) dalla colonna timestamp; le scritture nella tabella devono specificare solo i dati per la colonna timestamp. Tuttavia, se si specificano in modo esplicito i valori, i valori devono soddisfare il vincolo (<value> <=> <generation expression>) IS TRUE o la scrittura avrà esito negativo con un errore.

Importante

Le tabelle create con colonne generate hanno una versione del protocollo del writer di tabelle superiore rispetto all'impostazione predefinita. Vedere In che modo Azure Databricks gestisce la compatibilità delle funzionalità Delta Lake? per comprendere il controllo delle versioni dei protocolli di tabella e cosa significa avere una versione più recente di una versione del protocollo di tabella.

Creare una tabella con colonne generate

Nel codice di esempio seguente viene illustrato come creare una nuova tabella con il metodo .

SQL

CREATE TABLE default.people10m (
  id INT,
  firstName STRING,
  middleName STRING,
  lastName STRING,
  gender STRING,
  birthDate TIMESTAMP,
  dateOfBirth DATE GENERATED ALWAYS AS (CAST(birthDate AS DATE)),
  ssn STRING,
  salary INT
)

Python

DeltaTable.create(spark) \
  .tableName("default.people10m") \
  .addColumn("id", "INT") \
  .addColumn("firstName", "STRING") \
  .addColumn("middleName", "STRING") \
  .addColumn("lastName", "STRING", comment = "surname") \
  .addColumn("gender", "STRING") \
  .addColumn("birthDate", "TIMESTAMP") \
  .addColumn("dateOfBirth", DateType(), generatedAlwaysAs="CAST(birthDate AS DATE)") \
  .addColumn("ssn", "STRING") \
  .addColumn("salary", "INT") \
  .execute()

Scala

DeltaTable.create(spark)
  .tableName("default.people10m")
  .addColumn("id", "INT")
  .addColumn("firstName", "STRING")
  .addColumn("middleName", "STRING")
  .addColumn(
    DeltaTable.columnBuilder("lastName")
      .dataType("STRING")
      .comment("surname")
      .build())
  .addColumn("lastName", "STRING", comment = "surname")
  .addColumn("gender", "STRING")
  .addColumn("birthDate", "TIMESTAMP")
  .addColumn(
    DeltaTable.columnBuilder("dateOfBirth")
     .dataType(DateType)
     .generatedAlwaysAs("CAST(dateOfBirth AS DATE)")
     .build())
  .addColumn("ssn", "STRING")
  .addColumn("salary", "INT")
  .execute()

Le colonne generate vengono archiviate come se fossero colonne normali. Cioè occupano spazio di archiviazione.

Agli assembly ritirabili si applicano le seguenti restrizioni:

  • Un'espressione di generazione può usare qualsiasi funzione SQL in Spark che restituisce sempre lo stesso risultato quando vengono specificati gli stessi valori di argomento, ad eccezione dei tipi di funzioni seguenti:
    • Funzioni definite dall'utente.
    • Funzioni di aggregazione.
    • Funzioni finestra
    • Funzioni che restituiscono più righe.

Delta Lake può generare filtri di partizione per una query ogni volta che una colonna di partizione è definita da una delle espressioni seguenti:

Nota

Photon è obbligatorio in Databricks Runtime 10.4 LTS e versioni successive. Photon non è obbligatorio in Databricks Runtime 11.3 LTS e versioni successive.

  • CAST(col AS DATE) e di tipo di col è TIMESTAMP.
  • YEAR(col) e di tipo di col è TIMESTAMP.
  • Due colonne di partizione definite da YEAR(col), MONTH(col) e il tipo di col è TIMESTAMP.
  • Tre colonne di partizione definite da YEAR(col), MONTH(col), DAY(col) e il tipo di col è TIMESTAMP.
  • Quattro colonne di partizione definite da YEAR(col), MONTH(col), DAY(col), HOUR(col) e il tipo di col è TIMESTAMP.
  • SUBSTRING(col, pos, len) e il tipo di col è STRING
  • DATE_FORMAT(col, format) e di tipo di col è TIMESTAMP.
    • È possibile usare solo i formati di data con i modelli seguenti: yyyy-MM e yyyy-MM-dd-HH.
    • In Databricks Runtime 10.4 LTS e versioni successive è anche possibile usare il modello seguente: yyyy-MM-dd.

Se una colonna di partizione è definita da una delle espressioni precedenti e una query filtra i dati usando la colonna di base sottostante di un'espressione di generazione, Delta Lake esamina la relazione tra la colonna di base e la colonna generata e popola i filtri di partizione in base alla colonna di partizione generata, se possibile. Si consideri, ad esempio, il codice XML seguente:

CREATE TABLE events(
eventId BIGINT,
data STRING,
eventType STRING,
eventTime TIMESTAMP,
eventDate date GENERATED ALWAYS AS (CAST(eventTime AS DATE))
)
PARTITIONED BY (eventType, eventDate)

Eseguire la query seguente.

SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" <= "2020-10-01 12:00:00"

Delta Lake genera automaticamente un filtro di partizione in modo che la query precedente legga solo i dati nella partizione anche se non viene specificato un filtro di partizione date=2020-10-01 .

Per un esempio, fare riferimento alla tabella seguente.

CREATE TABLE events(
eventId BIGINT,
data STRING,
eventType STRING,
eventTime TIMESTAMP,
year INT GENERATED ALWAYS AS (YEAR(eventTime)),
month INT GENERATED ALWAYS AS (MONTH(eventTime)),
day INT GENERATED ALWAYS AS (DAY(eventTime))
)
PARTITIONED BY (eventType, year, month, day)

Eseguire la query seguente.

SELECT * FROM events
WHERE eventTime >= "2020-10-01 00:00:00" <= "2020-10-01 12:00:00"

Delta Lake genera automaticamente un filtro di partizione in modo che la query precedente legga solo i dati nella partizione anche se non viene specificato un filtro di partizione year=2020/month=10/day=01 .

È possibile usare una clausola EXPLAIN e controllare il piano fornito per verificare se Delta Lake genera automaticamente eventuali filtri di partizione.

Usare le colonne Identity in Delta Lake

Importante

La dichiarazione di una colonna Identity in una tabella Delta disabilita le transazioni simultanee. Usare solo le colonne Identity nei casi d'uso in cui le scritture simultanee nella tabella di destinazione non sono necessarie.

Le colonne Identity delta Lake sono un tipo di colonna generata che assegna valori univoci per ogni record inserito in una tabella. Nell'esempio seguente viene illustrata la sintassi di base per dichiarare una colonna Identity durante un'istruzione create table:

SQL

CREATE TABLE table_name (
  id_col1 BIGINT GENERATED ALWAYS AS IDENTITY,
  id_col2 BIGINT GENERATED ALWAYS AS IDENTITY (START WITH -1 INCREMENT BY 1),
  id_col3 BIGINT GENERATED BY DEFAULT AS IDENTITY,
  id_col4 BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH -1 INCREMENT BY 1)
 )

Python

from delta.tables import DeltaTable, IdentityGenerator
from pyspark.sql.types import LongType

DeltaTable.create()
  .tableName("table_name")
  .addColumn("id_col1", dataType=LongType(), generatedAlwaysAs=IdentityGenerator())
  .addColumn("id_col2", dataType=LongType(), generatedAlwaysAs=IdentityGenerator(start=-1, step=1))
  .addColumn("id_col3", dataType=LongType(), generatedByDefaultAs=IdentityGenerator())
  .addColumn("id_col4", dataType=LongType(), generatedByDefaultAs=IdentityGenerator(start=-1, step=1))
  .execute()

Scala

import io.delta.tables.DeltaTable
import org.apache.spark.sql.types.LongType

DeltaTable.create(spark)
  .tableName("table_name")
  .addColumn(
    DeltaTable.columnBuilder(spark, "id_col1")
      .dataType(LongType)
      .generatedAlwaysAsIdentity().build())
  .addColumn(
    DeltaTable.columnBuilder(spark, "id_col2")
      .dataType(LongType)
      .generatedAlwaysAsIdentity(start = -1L, step = 1L).build())
  .addColumn(
    DeltaTable.columnBuilder(spark, "id_col3")
      .dataType(LongType)
      .generatedByDefaultAsIdentity().build())
  .addColumn(
    DeltaTable.columnBuilder(spark, "id_col4")
      .dataType(LongType)
      .generatedByDefaultAsIdentity(start = -1L, step = 1L).build())
  .execute()

Nota

Le API Scala e Python per le colonne Identity sono disponibili in Databricks Runtime 16.0 e versioni successive.

Per visualizzare tutte le opzioni di sintassi SQL per la creazione di tabelle con colonne Identity, vedere CREATE TABLE [USING].

È possibile specificare l'opzione seguente:

  • Valore iniziale
  • Dimensione del passaggio, che può essere positiva o negativa.

Sia il valore iniziale che le dimensioni dei passaggi sono predefinito per 1. Non è possibile specificare le dimensioni di un passaggio pari 0a .

I valori assegnati dalle colonne Identity sono univoci e incrementi nella direzione del passaggio specificato e in multipli delle dimensioni del passaggio specificate, ma non sono garantiti contigui. Ad esempio, con un valore iniziale di 0 e una dimensione di passaggio pari 2a , tutti i valori sono numeri pari positivi, ma alcuni numeri pari potrebbero essere ignorati.

Quando si usa la clausola , le operazioni di inserimento GENERATED BY DEFAULT AS IDENTITYpossono specificare valori per la colonna Identity. Modificare la clausola in modo da GENERATED ALWAYS AS IDENTITY eseguire l'override della possibilità di impostare manualmente i valori.

Le colonne Identity supportano solo il BIGINT tipo e le operazioni hanno esito negativo se il valore assegnato supera l'intervallo supportato da BIGINT.

Per informazioni sulla sincronizzazione dei valori delle colonne Identity con i dati, vedere ALTER TABLE ... Clausola COLUMN.

Colonne CTAS e Identity

Non è possibile definire schemi, vincoli di colonna Identity o altre specifiche di tabella quando si usa un'istruzione CREATE TABLE table_name AS SELECT (CTAS).

Per creare una nuova tabella con una colonna Identity e popolarla con i dati esistenti, eseguire le operazioni seguenti:

  1. Creare una tabella con lo schema corretto, inclusa la definizione della colonna Identity e altre proprietà della tabella.
  2. Eseguire un’operazione INSERT.

Nell'esempio seguente viene utilizzata la DEFAULT parola chiave per definire la colonna Identity. Se i dati inseriti nella tabella includono valori validi per la colonna Identity, questi valori vengono usati.

CREATE OR REPLACE TABLE new_table (
  id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 5),
  event_date DATE,
  some_value BIGINT
);

-- Inserts records including existing IDs
INSERT INTO new_table
SELECT id, event_date, some_value FROM old_table;

-- Insert records and generate new IDs
INSERT INTO new_table
SELECT event_date, some_value FROM new_records;

Limitazioni delle colonne Identity

Quando si utilizzano colonne Identity, esistono le limitazioni seguenti:

  • Le transazioni simultanee non sono supportate nelle tabelle con colonne Identity abilitate.
  • Non è possibile partizionare una tabella in base a una colonna Identity.
  • Non è possibile usare ALTER TABLE per ADD, REPLACEo CHANGE una colonna Identity.
  • Non è possibile aggiornare il valore di una colonna Identity per un record esistente.

Nota

Per modificare il IDENTITY valore di un record esistente, è necessario eliminare il record e INSERT come nuovo record.