Генерируемые столбцы Delta Lake

Внимание

Эта функция доступна в общедоступной предварительной версии.

Вычисляемые столбцы Delta Lake автоматически вычисляют и сохраняют значения на основе выражения, заданного пользователем, по другим столбцам таблицы. При записи в таблицу без предоставления значений для созданных столбцов Delta Lake вычисляет их автоматически. Если вы указываете значения, они должны удовлетворять условию (<value> <=> <generation expression>) IS TRUE, иначе запись завершится ошибкой. См. Ограничения в Azure Databricks.

Например, можно вычислить столбец price_with_tax из base_price * 1.1, не требуя указывать данные для price_with_tax при записи.

Как и обычные столбцы, созданные столбцы физически хранятся в базовых файлах данных таблицы.

Note

Включение созданных столбцов обновляет протокол записи таблиц. Это может повлиять на совместимость с внешними клиентами Delta Lake. См. сведения о совместимости функций Delta Lake и протоколах.

Создание таблицы с созданными столбцами

В следующем примере показано, как создать таблицу с созданными столбцами:

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

Поддерживаемые выражения

Выражение поколения может использовать любую детерминированную функцию SQL, которая всегда возвращает одинаковый результат для одних и того же входных данных. Рассмотрим пример.

  • Арифметика: base_price * 1.1
  • Строковые функции: CONCAT(first_name, ' ', last_name), SUBSTRING(col, 1, 3)
  • Функции даты: CAST(birthDate AS DATE), YEAR(eventTime)

Следующие типы функций не поддерживаются:

  • Функции, определённые пользователем
  • Агрегатные функции
  • Функции окна
  • Функции, возвращающие несколько строк

Создание фильтра разделов

Note

Databricks рекомендует кластеризацию жидкости для всех новых таблиц Delta Lake. См. раздел "Использование кластеризации жидкости" для таблиц.

При секционировании таблицы с использованием вычисляемого столбца и выполнении запроса по базовому столбцу Delta Lake автоматически выводит фильтры секционирования, если это возможно. Не требуется явно фильтровать по сгенерированному столбцу разделов. Delta Lake выводит диапазон секций из базового значения столбца.

Фотон требуется в Databricks Runtime 10.4 LTS и ниже. Фотон не требуется в Databricks Runtime 11.3 LTS и более поздних версиях.

Создание фильтра секций поддерживается для следующих выражений:

  • CAST(col AS DATE) и тип col — TIMESTAMP.
  • YEAR(col) и тип col — TIMESTAMP.
  • Два столбца секции определяются YEAR(col), MONTH(col) и col, а тип col — это .
  • Три столбца секции, определяемые при помощи YEAR(col), MONTH(col), DAY(col), а тип colTIMESTAMP.
  • Четыре столбца раздела, определенные YEAR(col), MONTH(col), DAY(col), HOUR(col), и тип colTIMESTAMP.
  • SUBSTRING(col, pos, len) и тип col — STRING.
  • DATE_FORMAT(col, format) и тип col — TIMESTAMP.
    • Форматы дат можно использовать только со следующими шаблонами: yyyy-MM и yyyy-MM-dd-HH.
    • В Databricks Runtime 10.4 LTS и более поздних версиях можно также использовать следующий шаблон: yyyy-MM-dd

Пример: одна секция

Например, учитывая следующую таблицу:

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

Если вы затем выполните следующий запрос:

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

Delta Lake автоматически создает фильтр секций, чтобы предыдущий запрос только считывал данные в разделе date=2020-10-01 даже если фильтр секции не указан.

Используйте условие EXPLAIN и проверьте предоставленный план, чтобы узнать, создает ли Delta Lake автоматически какие-либо фильтры по разделам.

Пример: несколько разделов

Например, учитывая следующую таблицу:

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)

Если вы затем выполните следующий запрос:

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

Delta Lake автоматически создает фильтр секций, чтобы предыдущий запрос только считывал данные в разделе year=2020/month=10/day=01 даже если фильтр секции не указан.

Используйте условие EXPLAIN и проверьте предоставленный план, чтобы узнать, автоматически создает ли Delta Lake какие-либо фильтры по разделам.

Столбцы идентификаторов

Внимание

При объявлении столбца идентификаторов в таблице Delta Lake параллельные транзакции отключаются. Используйте столбцы идентификаторов только в тех случаях, когда одновременная запись в целевую таблицу не требуется. См. ограничения столбцов идентификаторов.

Идентификационные столбцы Delta Lake — это тип сгенерированного столбца, который назначает уникальные значения для каждой записи, вставленной в таблицу. В следующем примере показан базовый синтаксис для объявления столбца идентификатора в инструкции создания таблицы.

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

Note

API Scala и Python для идентичных столбцов доступны в Databricks Runtime 16.0 и выше.

Чтобы просмотреть все параметры синтаксиса SQL для создания таблиц со столбцами идентификаторов, см. CREATE TABLE[USING].

При необходимости можно указать следующее:

  • Начальное значение.
  • Размер шага, который может быть положительным или отрицательным.

Начальное значение и размер шага по умолчанию 1. Невозможно указать размер шага 0.

Значения, назначенные identity-столбцами, являются уникальными и увеличиваются соответственно указанному шагу, и в кратных значениях указанного шага, но их непрерывность не гарантируется. Например, с начальным значением 0 и размером шага 2все значения - положительные четные числа, но некоторые числа могут быть пропущены.

При использовании предложения GENERATED BY DEFAULT AS IDENTITYоперации вставки могут указывать значения для столбца идентичности. Измените условие на GENERATED ALWAYS AS IDENTITY, чтобы переопределить возможность вручную задавать значения.

Колонки идентификаторов поддерживают только тип BIGINT, а операции завершаются ошибкой, если назначенное значение превышает диапазон, поддерживаемый BIGINT.

Сведения о синхронизации значений столбцов удостоверений с данными см. в ALTER TABLE ... COLUMN пункте.

Столбцы CTAS и столбцы идентификаторов

Невозможно определить схему, ограничения столбца с идентификатором или другие параметры таблицы при использовании оператора CREATE TABLE table_name AS SELECT (CTAS).

Чтобы создать новую таблицу со столбцом идентификаторов и заполнить её существующими данными, выполните следующие действия:

  1. Создайте таблицу с правильной схемой, включая определение столбца с идентичностью и другие свойства таблицы.
  2. Выполните операцию INSERT.

В следующем примере для определения столбца идентификаторов используется ключевое слово DEFAULT. Если данные, вставляемые в таблицу, содержат допустимые значения для столбца идентификаторов, эти значения используются.

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 (id, event_date, some_value)
SELECT id, event_date, some_value FROM old_table;

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

Ограничения столбца идентификаторов

При работе с идентификационными столбцами существуют следующие ограничения:

  • Одновременные транзакции не поддерживаются в таблицах с включенными идентификационными столбцами.
  • Нельзя секционировать таблицу по столбцу идентификаторов.
  • Нельзя использовать ALTER TABLEADDдля столбца REPLACEудостоверений или CHANGE столбца удостоверения.
  • Невозможно обновить значение столбца идентификаторов для существующей записи.

Note

Чтобы изменить значение IDENTITY для существующей записи, необходимо удалить эту запись и занести её INSERT как новую запись.

Созданные столбцы и маски столбцов

Созданный столбец не может ссылаться на столбец, имеющий маску столбца, примененную, так как созданное значение покажет базовые данные, защищенные маской. Это вызывает ошибку, и запрос завершается ошибкой. См. фильтры строк и маски столбцов.

Ниже приведены примеры ошибок:

  • Невозможно создать созданный столбец, выражение которого ссылается на маскированный столбец. COLUMN_MASKSВозвращает _GENERATED_COLUMN_UNSUPPORTED.

    CREATE TABLE tbl (
      a INT MASK masking_function,
      generated_col INT GENERATED ALWAYS AS (a + 1)
    ) USING DELTA;
    
  • Маску столбца нельзя применить к столбцу, который уже ссылается на созданный столбец. COLUMN_MASKSВызывает _REFERENCED_BY_GENERATED_COLUMN.ADD_MASK.

    CREATE TABLE tbl (
      a INT,
      generated_col INT GENERATED ALWAYS AS (a + 1)
    ) USING DELTA;
    
    ALTER TABLE tbl ALTER COLUMN a SET MASK masking_function;
    
  • Считывание из таблицы, в которой созданный столбец уже ссылается на маскированный столбец, также заблокировано. Вызывает COLUMN_MASKS_REFERENCED_BY_GENERATED_COLUMN.READ_BLOCKED.

Чтобы устранить все эти ошибки, необходимо изменить таблицу, чтобы созданные столбцы и маскированные столбцы не перекрывались.