Dela via


Delta Lake genererad columns

Viktigt!

Den här funktionen finns som allmänt tillgänglig förhandsversion.

Delta Lake stöder genererade columns som är en särskild typ av column vars values genereras automatiskt baserat på en användardefinerad funktion jämfört med andra columns i Delta table. När du skriver till en table med genererade columns utan att uttryckligen ange values för dem, beräknar Delta Lake automatiskt values. Man kan till exempel automatiskt generate ett datum column (för att partitionera table efter datum) från tidsstämpeln column; alla skrivningar till table behöver bara ange data för tidsstämpeln column. Men om du uttryckligen anger values för dem måste values uppfylla constraint(<value> <=> <generation expression>) IS TRUE, annars misslyckas skrivningen med ett fel.

Viktigt!

Tables som skapats med genererade columns har en högre table skrivprotokollversion än standardversionen. Se Hur hanterar Azure Databricks Delta Lake-funktionskompatibilitet? att förstå table protokollversioner och vad det innebär att ha en högre version av en table protokollversion.

Skapa en table med genererade columns

I följande exempel visas hur du skapar en table med genererade columns:

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()

Genererade columns lagras som om de vore normala columns. Det vill säger att de upptar lagring.

Följande begränsningar gäller för genererade columns:

  • Ett generationsuttryck kan använda alla SQL-funktioner i Spark som alltid returnerar samma resultat när samma argument values, förutom följande typer av funktioner:
    • Användardefinierade funktioner.
    • Mängdfunktioner.
    • Window funktioner.
    • Funktioner som returnerar flera rader.

Delta Lake kan generatepartition filter för en sökfråga när en partitioncolumn definieras av något av följande uttryck:

Kommentar

Photon krävs i Databricks Runtime 10.4 LTS och nedan. Photon krävs inte i Databricks Runtime 11.3 LTS och senare.

  • CAST(col AS DATE) och typen av col är TIMESTAMP.
  • YEAR(col) och typen av col är TIMESTAMP.
  • Två partitioncolumns definieras av YEAR(col), MONTH(col) och typen av col är TIMESTAMP.
  • Tre partitioncolumns definieras av YEAR(col), MONTH(col), DAY(col) och typen av col är TIMESTAMP.
  • Fyra partitioncolumns definieras av YEAR(col), MONTH(col), DAY(col), HOUR(col) och typen av col är TIMESTAMP.
  • SUBSTRING(col, pos, len) och typen av col är STRING
  • DATE_FORMAT(col, format) och typen av col är TIMESTAMP.
    • Du kan bara använda datumformat med följande mönster: yyyy-MM och yyyy-MM-dd-HH.
    • I Databricks Runtime 10.4 LTS och senare kan du också använda följande mönster: yyyy-MM-dd.

Om en partitioncolumn definieras av ett av ovanstående uttryck och en fråga filtrerar data med hjälp av den underliggande basen column för ett generationsuttryck, tittar Delta Lake på relationen mellan bas-column och den genererade columnoch fyller i partition filter baserat på den genererade partitioncolumn om möjligt. Till exempel med följande table:

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

Om du sedan kör följande fråga:

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

Delta Lake genererar automatiskt ett partition filter så att föregående fråga endast läser data i partitiondate=2020-10-01 även om ett partition filter inte har angetts.

Som ett annat exempel, givet följande table:

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)

Om du sedan kör följande fråga:

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

Delta Lake genererar automatiskt ett partition filter så att föregående fråga endast läser data i partitionyear=2020/month=10/day=01 även om ett partition filter inte har angetts.

Du kan använda en EXPLAIN-sats och kontrollera den angivna planen för att se om Delta Lake automatiskt genererar några partition filter.

Använd identitet columns i Delta Lake

Viktigt!

Om du deklarerar en identitet column på en Delta-table inaktiveras samtidiga transaktioner. Använd endast identitet columns i användningsfall where där samtidiga skrivningar till målet table inte är nödvändiga.

Delta Lake-identitet columns är en typ av genererad column som tilldelar unika values för varje post som infogas i en table. I följande exempel visas den grundläggande syntaxen för att deklarera en identitet column i ett skapa-uttalande 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()

Kommentar

Scala- och Python-API:er för identitet columns är tillgängliga i Databricks Runtime 16.0 och senare.

Om du vill se alla SQL-syntaxalternativ för att skapa tables med identitet columnsläser du CREATE TABLE [USING].

Du kan också ange följande:

  • Ett startvärde.
  • En stegstorlek som kan vara positiv eller negativ.

Både startvärdet och stegstorleken är standardvärdet 1. Du kan inte ange en stegstorlek på 0.

Values som tilldelas av identitet columns är unika och ökar enligt det angivna steget och i multiplar av den angivna stegstorleken, men är inte garanterat sammanhängande. Med ett startvärde på 0 och en stegstorlek på 2är alla values positiva jämna tal, men vissa jämna tal kan hoppas över.

När du använder satsen GENERATED BY DEFAULT AS IDENTITYkan åtgärderna insert ange values för identiteten column. Ändra klausulen till GENERATED ALWAYS AS IDENTITY för att åsidosätta möjligheten att manuellt setvalues.

Identiteten columns stöder endast BIGINT-typ, och operationer misslyckas om det tilldelade värdet överskrider det intervall som stöds av BIGINT.

För att lära dig om att synkronisera identitet columnvalues med data, se ALTER TABLE ... COLUMN klausul.

CTAS och identitet columns

Du kan inte definiera schema, identitetsbegränsningar column eller andra table specifikationer när du använder en CREATE TABLE table_name AS SELECT-instruktion (CTAS).

Om du vill skapa en ny table med en identitet column och fylla den med befintliga data gör du följande:

  1. Skapa en table med rätt schema, inklusive identitetsdefinitionen column och andra egenskaper för table.
  2. Kör en INSERT åtgärd.

I följande exempel används nyckelordet DEFAULT för att definiera identiteten column. Om data, som infogas i table, innehåller giltiga values för identiteten column, används dessa values.

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;

Begränsningar för identitet column

Följande begränsningar finns när du arbetar med identitet columns:

  • Samtidiga transaktioner stöds inte på tables med identitet columns aktiverad.
  • Du kan inte partition en table med en identitet column.
  • Du kan inte använda ALTER TABLE för att ADD, REPLACEeller CHANGE en identitet column.
  • Du kan inte update värdet för en identitet column för en befintlig post.

Kommentar

Om du vill ändra IDENTITY värdet för en befintlig post måste du ta bort posten och INSERT den som en ny post.