CREATE TABLE
Создает новую таблицу. Синтаксис этого запроса может различаться в зависимости от сценария использования.
По умолчанию таблицы создаются только на текущем сервере. Распределенные DDL-запросы реализованы с помощью предложения ON CLUSTER, которое описано отдельно.
Синтаксические формы
С явной схемой
Создаёт таблицу с именем table_name в базе данных db или в текущей базе данных, если db не задана, со структурой, указанной в скобках, и движком engine.
Структура таблицы — это список описаний столбцов, вторичных индексов и ограничений. Если движок поддерживает primary key, он указывается как параметр движка таблицы.
В простейшем случае описание столбца — это name type. Пример: RegionID UInt32.
Для значений по умолчанию также можно задать выражения (см. ниже).
При необходимости может быть указан первичный ключ с одним или несколькими выражениями ключа.
Комментарии могут быть добавлены как для столбцов, так и для таблицы.
Со схемой, аналогичной другой таблице
Создает таблицу с такой же структурой, как у другой таблицы. Вы можете указать для таблицы другой движок. Если движок не указан, используется тот же движок, что и для таблицы db2.name2.
Со схемой и данными, клонированными из другой таблицы
Создаёт таблицу с той же структурой, что и другая таблица. Можно указать для неё другой движок. Если движок не указан, будет использован тот же, что и у таблицы db2.name2. После создания новой таблицы к ней присоединяются все партиции из db2.name2. Другими словами, данные из db2.name2 клонируются в db.table_name при создании. Этот запрос эквивалентен следующему:
Из табличной функции
Создаёт таблицу с тем же результатом, что и указанная табличная функция. Созданная таблица также будет работать так же, как соответствующая табличная функция.
Из запроса SELECT
Создаёт таблицу со структурой, соответствующей результату запроса SELECT, с движком engine и заполняет её данными из SELECT. Также вы можете явно задать описание столбцов.
Если таблица уже существует и указано IF NOT EXISTS, запрос ничего не выполнит.
После секции ENGINE в запросе могут следовать и другие секции. Подробную документацию по созданию таблиц см. в описаниях движков таблиц.
Пример
Запрос:
Результат:
Модификаторы NULL и NOT NULL
Модификаторы NULL и NOT NULL после типа данных в определении столбца соответственно разрешают или запрещают делать его Nullable.
Если тип не является Nullable и указано NULL, он будет интерпретироваться как Nullable; если указано NOT NULL, то нет. Например, INT NULL — то же самое, что Nullable(INT). Если тип уже является Nullable и заданы модификаторы NULL или NOT NULL, будет сгенерировано исключение.
См. также настройку data_type_default_nullable.
Значения по умолчанию
Описание столбца может задавать выражение значения по умолчанию в виде DEFAULT expr, MATERIALIZED expr или ALIAS expr. Пример: URLDomain String DEFAULT domain(URL).
Выражение expr является необязательным. Если оно опущено, тип столбца должен быть явно указан, а значение по умолчанию будет 0 для числовых столбцов, '' (пустая строка) для строковых столбцов, [] (пустой массив) для столбцов‑массивов, 1970-01-01 для столбцов с типом дата или NULL для столбцов типа Nullable.
Тип столбца со значением по умолчанию можно не указывать, в этом случае он определяется из типа expr. Например, тип столбца EventDate DEFAULT toDate(EventTime) будет Date.
Если указаны и тип данных, и выражение значения по умолчанию, вставляется неявная функция приведения типа, которая преобразует выражение к указанному типу. Пример: Hits UInt32 DEFAULT 0 внутренне представляется как Hits UInt32 DEFAULT toUInt32(0).
Выражение значения по умолчанию expr может ссылаться на произвольные столбцы таблицы и константы. ClickHouse проверяет, что изменения структуры таблицы не приводят к появлению циклов в вычислении выражения. При выполнении INSERT проверяется, что выражения можно вычислить — что все столбцы, на основе которых они считаются, были переданы.
DEFAULT
DEFAULT expr
Обычное значение по умолчанию. Если значение такого столбца не указано в запросе INSERT, оно вычисляется из expr.
Пример:
MATERIALIZED
MATERIALIZED expr
Материализованное выражение. Значения таких столбцов автоматически вычисляются в соответствии с заданным материализованным выражением при вставке строк. Значения не могут быть явно заданы при выполнении INSERT.
Кроме того, столбцы этого типа со значением по умолчанию не включаются в результат SELECT *. Это нужно для сохранения инварианта, согласно которому результат SELECT * всегда можно вставить обратно в таблицу с помощью INSERT. Это поведение можно отключить с помощью настройки asterisk_include_materialized_columns.
Пример:
EPHEMERAL
EPHEMERAL [expr]
Эфемерный столбец. Столбцы этого типа не хранятся в таблице, и по ним нельзя выполнять SELECT. Единственное назначение эфемерных столбцов — использовать их при построении выражений значений по умолчанию для других столбцов.
При вставке без явного указания столбцов столбцы этого типа будут пропущены. Это сделано для сохранения инварианта, согласно которому результат SELECT * всегда может быть вставлен обратно в таблицу с помощью INSERT.
Пример:
Строка 1: ────── id: 1 hexed: Z�� hex(hexed): 5A90B714
Первичный ключ
Вы можете задать первичный ключ при создании таблицы. Первичный ключ можно указать двумя способами:
- Внутри списка столбцов
- Вне списка столбцов
Нельзя совмещать оба подхода в одном запросе.
Ограничения
Наряду с описаниями столбцов можно задать ограничения:
CONSTRAINT
boolean_expr_1 может представлять собой любое логическое выражение. Если для таблицы определены ограничения, каждое из них будет проверяться для каждой строки в запросе INSERT. Если какое-либо ограничение не выполняется, сервер сгенерирует исключение с именем ограничения и выражением проверки.
Добавление большого количества ограничений может негативно повлиять на производительность больших запросов INSERT.
ASSUME
Предложение ASSUME используется для определения CONSTRAINT в таблице, который считается истинным. Это ограничение затем может быть использовано оптимизатором для повышения производительности SQL-запросов.
Рассмотрим пример, где ASSUME CONSTRAINT используется при создании таблицы users_a:
Здесь ASSUME CONSTRAINT используется как утверждение, что результат функции length(name) всегда равен значению столбца name_len. Это означает, что всякий раз, когда length(name) вызывается в запросе, ClickHouse может заменить её на name_len, что должно быть быстрее, поскольку позволяет избежать вызова функции length().
Затем при выполнении запроса SELECT name FROM users_a WHERE length(name) < 5; ClickHouse может оптимизировать его до SELECT name FROM users_a WHERE name_len < 5; благодаря ASSUME CONSTRAINT. Это может ускорить выполнение запроса, потому что не требуется вычислять длину name для каждой строки.
ASSUME CONSTRAINT не обеспечивает выполнение ограничения, он лишь информирует оптимизатор, что ограничение соблюдается. Если ограничение на самом деле не выполняется, результаты запросов могут быть некорректными. Поэтому следует использовать ASSUME CONSTRAINT только в том случае, если вы уверены, что ограничение действительно выполняется.
Выражение TTL
Определяет срок хранения значений. Может быть задано только для таблиц семейства MergeTree. Для подробного описания см. раздел TTL для столбцов и таблиц.
Кодеки сжатия столбцов
По умолчанию ClickHouse использует сжатие lz4 в самостоятельной (self-managed) установке и zstd в ClickHouse Cloud.
Для семейства движков MergeTree вы можете изменить метод сжатия по умолчанию в разделе compression конфигурации сервера.
Вы также можете задать метод сжатия для каждого отдельного столбца в запросе CREATE TABLE.
Кодек Default можно указать для использования сжатия по умолчанию, которое во время выполнения может зависеть от различных настроек (и свойств данных).
Пример: value UInt64 CODEC(Default) — то же самое, что и отсутствие указания кодека.
Также вы можете удалить текущий CODEC из столбца и использовать сжатие по умолчанию из config.xml:
Кодеки можно комбинировать в конвейер, например, CODEC(Delta, Default).
Нельзя декомпрессировать файлы базы данных ClickHouse с помощью внешних утилит, таких как lz4. Вместо этого используйте специальную утилиту clickhouse-compressor.
Сжатие поддерживается для следующих движков таблиц:
- Семейство MergeTree. Поддерживает кодеки сжатия столбцов и выбор метода сжатия по умолчанию с помощью настроек compression.
- Семейство Log. По умолчанию использует метод сжатия
lz4и поддерживает кодеки сжатия столбцов. - Set. Поддерживается только сжатие по умолчанию.
- Join. Поддерживается только сжатие по умолчанию.
ClickHouse поддерживает кодеки как общего, так и специализированного назначения.
Кодеки общего назначения
NONE
NONE — без сжатия.
LZ4
LZ4 — используемый по умолчанию алгоритм сжатия данных без потерь. Применяет быстрое сжатие LZ4.
LZ4HC
LZ4HC[(level)] — алгоритм LZ4 HC (high compression, высокое сжатие) с настраиваемым уровнем. Уровень по умолчанию: 9. Значение level <= 0 приводит к использованию уровня по умолчанию. Возможные уровни: [1, 12]. Рекомендуемый диапазон уровней: [4, 9].
ZSTD
ZSTD[(level)] — алгоритм сжатия ZSTD с настраиваемым level. Возможные уровни: [1, 22]. Уровень по умолчанию: 1.
Высокие уровни сжатия полезны для асимметричных сценариев, например, когда данные один раз сжимаются и многократно распаковываются. Более высокие уровни обеспечивают лучшее сжатие и более высокую нагрузку на CPU.
ZSTD_QAT
ZSTD_QAT[(level)] — алгоритм сжатия ZSTD с настраиваемым уровнем, реализованный с помощью Intel® QATlib и Intel® QAT ZSTD Plugin. Возможные уровни: [1, 12]. Уровень по умолчанию: 1. Рекомендуемый диапазон уровней: [6, 12]. Применяются некоторые ограничения:
- ZSTD_QAT по умолчанию отключён и может использоваться только после включения настройки конфигурации enable_zstd_qat_codec.
- Для сжатия ZSTD_QAT пытается использовать аппаратное устройство Intel® QAT для разгрузки (QuickAssist Technology). Если такое устройство не найдено, выполняется переход к программному сжатию ZSTD.
- Распаковка всегда выполняется программно.
DEFLATE_QPL
DEFLATE_QPL — алгоритм сжатия Deflate, реализованный с помощью Intel® Query Processing Library. Применяются некоторые ограничения:
- DEFLATE_QPL отключен по умолчанию и может использоваться только после включения параметра конфигурации enable_deflate_qpl_codec.
- DEFLATE_QPL требует сборку ClickHouse, скомпилированную с использованием инструкций SSE 4.2 (по умолчанию это так). Подробнее см. в разделе Сборка ClickHouse с DEFLATE_QPL.
- DEFLATE_QPL работает наилучшим образом, если в системе есть устройство разгрузки Intel® IAA (In-Memory Analytics Accelerator). Подробнее см. Accelerator Configuration и Benchmark with DEFLATE_QPL.
- Данные, сжатые с помощью DEFLATE_QPL, могут передаваться только между узлами ClickHouse, скомпилированными с включённой SSE 4.2.
Специализированные кодеки
Эти кодеки предназначены для повышения эффективности сжатия за счёт использования специфических особенностей данных. Некоторые из этих кодеков не сжимают данные сами по себе, а предварительно обрабатывают их таким образом, чтобы второй этап сжатия с использованием универсального кодека мог достичь более высокой степени сжатия.
Delta
Delta(delta_bytes) — подход к сжатию, при котором исходные значения заменяются разностью двух соседних значений, за исключением первого значения, которое остаётся неизменным. delta_bytes — максимальный размер исходных значений, значение по умолчанию — sizeof(type). Указание delta_bytes в качестве аргумента устарело, и поддержка будет удалена в одной из будущих версий. Delta является кодеком подготовки данных, то есть не может использоваться самостоятельно.
DoubleDelta
DoubleDelta(bytes_size) — вычисляет разности разностей и записывает их в компактном двоичном формате. bytes_size имеет схожий смысл с delta_bytes в кодеке Delta. Указание bytes_size в качестве аргумента устарело, и поддержка будет удалена в одной из будущих версий. Оптимальные коэффициенты сжатия достигаются для монотонных последовательностей с постоянным шагом, например для данных временных рядов. Может использоваться с любым числовым типом. Реализует алгоритм, используемый в Gorilla TSDB, расширяя его для поддержки 64-битных типов. Использует 1 дополнительный бит для 32-битных дельт: 5-битные префиксы вместо 4-битных. Дополнительные сведения см. в разделе Compressing Time Stamps в статье Gorilla: A Fast, Scalable, In-Memory Time Series Database. DoubleDelta является кодеком подготовки данных, то есть не может использоваться самостоятельно.
GCD
GCD() — вычисляет наибольший общий делитель (GCD) значений в столбце, затем делит каждое значение на этот GCD. Может использоваться с целочисленными, десятичными и столбцами типов дата/время. Кодек хорошо подходит для столбцов со значениями, которые изменяются (увеличиваются или уменьшаются) кратно GCD, например 24, 28, 16, 24, 8, 24 (GCD = 4). GCD является кодеком подготовки данных, то есть не может использоваться самостоятельно.
Gorilla
Gorilla(bytes_size) — вычисляет XOR между текущим и предыдущим значением с плавающей точкой и записывает его в компактном двоичном формате. Чем меньше разница между последовательными значениями, то есть чем медленнее изменяется ряд значений, тем лучше коэффициент сжатия. Реализует алгоритм, используемый в Gorilla TSDB, расширяя его для поддержки 64-битных типов. Возможные значения bytes_size: 1, 2, 4, 8, значение по умолчанию — sizeof(type), если оно равно 1, 2, 4 или 8. Во всех остальных случаях — 1. Дополнительные сведения см. в разделе 4.1 статьи Gorilla: A Fast, Scalable, In-Memory Time Series Database.
FPC
FPC(level, float_size) — последовательно предсказывает следующее значение с плавающей запятой в последовательности, выбирая лучший из двух предикторов, затем выполняет XOR фактического значения с предсказанным и сжимает результат, обрезая ведущие нули. Аналогично алгоритму Gorilla, это эффективно при хранении последовательности значений с плавающей запятой, которые изменяются медленно. Для 64-битных значений (double) FPC работает быстрее, чем Gorilla, для 32-битных значений производительность может отличаться. Возможные значения level: 1–28, значение по умолчанию — 12. Возможные значения float_size: 4, 8, значение по умолчанию — sizeof(type), если тип — Float. Во всех остальных случаях — 4. Подробное описание алгоритма см. в статье High Throughput Compression of Double-Precision Floating-Point Data.
T64
T64 — метод сжатия, который обрезает неиспользуемые старшие биты значений целочисленных типов данных (включая Enum, Date и DateTime). На каждом шаге алгоритма кодек берёт блок из 64 значений, помещает их в матрицу 64×64 бит, транспонирует её, обрезает неиспользуемые биты значений и возвращает остальное в виде последовательности. Неиспользуемые биты — это биты, которые не отличаются между максимальным и минимальным значениями во всей части данных, для которой используется сжатие.
Кодеки DoubleDelta и Gorilla используются в Gorilla TSDB как компоненты её алгоритма сжатия. Подход Gorilla эффективен в сценариях, когда есть последовательность медленно изменяющихся значений с их временными метками. Временные метки эффективно сжимаются кодеком DoubleDelta, а значения — кодеком Gorilla. Например, чтобы таблица эффективно хранилась, вы можете создать её в следующей конфигурации:
Кодеки шифрования
Эти кодеки на самом деле не сжимают данные, а вместо этого шифруют данные на диске. Они доступны только в том случае, если ключ шифрования задан в настройках encryption. Обратите внимание, что шифрование имеет смысл только в конце цепочек кодеков, потому что зашифрованные данные обычно нельзя сжать сколь‑нибудь эффективным образом.
Кодеки шифрования:
AES_128_GCM_SIV
CODEC('AES-128-GCM-SIV') — Шифрует данные с помощью AES-128 в режиме GCM-SIV согласно RFC 8452.
AES-256-GCM-SIV
CODEC('AES-256-GCM-SIV') — Шифрует данные с помощью AES-256 в режиме GCM-SIV.
Эти кодеки используют фиксированный nonce, и, следовательно, шифрование является детерминированным. Это делает их совместимыми с движками с дедупликацией, такими как ReplicatedMergeTree, но имеет слабое место: когда один и тот же блок данных шифруется дважды, результирующий зашифрованный текст будет в точности одинаковым, поэтому противник, который может читать диск, увидит это соответствие (хотя только соответствие, не получая его содержимое).
Большинство движков, включая семейство "*MergeTree", создают файлы индексов на диске без применения кодеков. Это означает, что незашифрованные данные будут присутствовать на диске, если зашифрованный столбец индексируется.
Если вы выполняете запрос SELECT, в котором упоминается конкретное значение в зашифрованном столбце (например, в предложении WHERE), это значение может появиться в system.query_log. Возможно, вы захотите отключить такое логирование.
Пример
Если требуется сжатие, его необходимо явно указать. В противном случае к данным будет применено только шифрование.
Пример
Временные таблицы
Обратите внимание, что временные таблицы не реплицируются. В результате нет гарантии, что данные, вставленные во временную таблицу, будут доступны на других репликах. Основной сценарий использования временных таблиц — выполнение запросов или JOIN с небольшими внешними наборами данных в рамках одной сессии.
ClickHouse поддерживает временные таблицы, которые обладают следующими характеристиками:
- Временные таблицы исчезают при завершении сессии, в том числе в случае потери соединения.
- Временная таблица использует движок таблицы Memory, если движок не указан, и может использовать любой движок таблиц, кроме движков Replicated и
KeeperMap. - Для временной таблицы нельзя указать БД. Она создаётся вне баз данных.
- Невозможно создать временную таблицу с распределённым DDL-запросом на всех серверах кластера (с использованием
ON CLUSTER): такая таблица существует только в текущей сессии. - Если временная таблица имеет то же имя, что и другая таблица, и в запросе указано только имя таблицы без указания БД, будет использоваться временная таблица.
- Для распределённой обработки запросов временные таблицы с движком Memory, используемые в запросе, передаются на удалённые серверы.
Для создания временной таблицы используйте следующий синтаксис:
В большинстве случаев временные таблицы не создаются вручную, а автоматически создаются при использовании внешних данных в запросе или для распределённого оператора (GLOBAL) IN. Для получения дополнительной информации см. соответствующие разделы.
Вместо временных таблиц можно использовать таблицы с движком ENGINE = Memory.
REPLACE TABLE
Оператор REPLACE позволяет атомарно обновлять таблицу.
Этот оператор поддерживается для движков баз данных Atomic и Replicated,
используемых по умолчанию в ClickHouse и ClickHouse Cloud соответственно.
Обычно, если вам нужно удалить часть данных из таблицы,
вы можете создать новую таблицу и заполнить её запросом SELECT, который не извлекает ненужные данные,
затем удалить старую таблицу и переименовать новую.
Этот подход демонстрируется в примере ниже:
Вместо описанного выше подхода вы также можете использовать REPLACE (при использовании движков баз данных по умолчанию), чтобы получить тот же результат:
Синтаксис
Все варианты синтаксиса оператора CREATE также применимы к данному оператору. Вызов REPLACE для несуществующей таблицы приведёт к ошибке.
Примеры:
- Локально
- Облако
Рассмотрим следующую таблицу:
Мы можем использовать оператор REPLACE, чтобы очистить все данные:
Или мы можем использовать оператор REPLACE, чтобы изменить структуру таблицы:
Рассмотрим следующую таблицу в ClickHouse Cloud:
Мы можем использовать оператор REPLACE, чтобы очистить все данные:
Или мы можем использовать оператор REPLACE, чтобы изменить структуру таблицы:
Предложение COMMENT
При создании таблицы вы можете добавить к ней комментарий.
Синтаксис
Пример
Запрос:
Результат: