ON CLUSTER, которое описано отдельно.
Варианты синтаксиса
С явной схемой
table_name в базе данных db или в текущей базе данных, если db не задана, со структурой, указанной в скобках, и движком engine.
Структура таблицы представляет собой список описаний столбцов, вторичных индексов, проекций и ограничений. Если первичный ключ поддерживается движком, он указывается как параметр движка таблицы.
В простейшем случае описание столбца имеет вид name type. Пример: RegionID UInt32.
Для значений по умолчанию также можно задавать выражения (см. ниже).
При необходимости можно указать первичный ключ с одним или несколькими ключевыми выражениями.
Для столбцов и таблицы можно добавлять комментарии.
Со схемой существующей таблицы
Со схемой и данными существующей таблицы
db.table. Иными словами, при создании данные из db.table клонируются в db2.table_clone. Этот запрос эквивалентен следующему:
db.table).
Из табличной функции
Из запроса SELECT
SELECT, с движком engine и заполняет её данными из SELECT. Также можно явно указать описание столбцов.
Если таблица уже существует и указано IF NOT EXISTS, запрос не выполнит никаких действий.
В запросе после предложения ENGINE могут следовать и другие предложения. Подробную документацию о том, как создавать таблицы, см. в описаниях движков таблиц.
Пример
Query
Response
Модификаторы 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 для числовых столбцов, '' (пустая строка) для строковых столбцов, [] (пустой массив) для столбцов типа Array, 1970-01-01 для столбцов с типом Date или 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.
Пример:
ALIAS
ALIAS expr
Вычисляемые столбцы (синоним). Столбцы этого типа не хранятся в таблице, и в них нельзя вставлять значения.
Когда запросы SELECT явно обращаются к столбцам этого типа, значение вычисляется во время выполнения запроса из expr. По умолчанию SELECT * исключает столбцы ALIAS. Это поведение можно отключить с помощью настройки asterisk_include_alias_columns.
При использовании запроса ALTER для добавления новых столбцов старые данные для этих столбцов не записываются. Вместо этого при чтении старых данных, в которых нет значений для новых столбцов, выражения по умолчанию вычисляются на лету. Однако если для вычисления выражений требуются другие столбцы, не указанные в запросе, эти столбцы также будут прочитаны, но только для тех блоков данных, где это необходимо.
Если вы добавите новый столбец в таблицу, а затем измените его выражение по умолчанию, значения, используемые для старых данных, изменятся (для данных, значения которых не были сохранены на диске). Обратите внимание, что при выполнении фоновых слияний данные для столбцов, отсутствующих в одной из сливающихся частей, записываются в слитую часть.
Невозможно задать значения по умолчанию для элементов во вложенных структурах данных.
При создании таблицы можно определить первичный ключ. Первичный ключ можно задать двумя способами:
- В списке столбцов
- Вне списка столбцов
Ограничения
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
Кодеки сжатия столбцов
lz4, а в ClickHouse Cloud — zstd.
Для семейства движков MergeTree метод сжатия по умолчанию можно изменить в разделе compression конфигурации сервера.
Метод сжатия также можно задать для каждого отдельного столбца в запросе CREATE TABLE.
Default можно указать, чтобы использовать сжатие по умолчанию, которое во время выполнения может зависеть от различных настроек (и свойств данных).
Пример: value UInt64 CODEC(Default) — то же самое, что и отсутствие указания кодека.
Также можно удалить текущий CODEC из столбца и использовать сжатие по умолчанию из config.xml:
CODEC(Delta, Default).
Сжатие поддерживается для следующих движков таблиц:
- Семейство MergeTree. Поддерживает кодеки сжатия для столбцов и выбор метода сжатия по умолчанию через настройки compression.
- Семейство Log. По умолчанию использует метод сжатия
lz4и поддерживает кодеки сжатия для столбцов. - Set. Поддерживается только сжатие по умолчанию.
- Join. Поддерживается только сжатие по умолчанию.
Кодеки общего назначения
NONE
NONE — без сжатия.
LZ4
LZ4 — алгоритм сжатия данных без потерь, используемый по умолчанию. Использует быстрое сжатие LZ4.
LZ4HC
LZ4HC[(level)] — алгоритм LZ4 HC (высокая степень сжатия) с настраиваемым уровнем. Уровень по умолчанию: 9. Если задано level <= 0, используется уровень по умолчанию. Допустимые уровни: [1, 12]. Рекомендуемый диапазон уровней: [4, 9].
ZSTD
ZSTD[(level)] — алгоритм сжатия ZSTD с настраиваемым level. Возможные уровни: [1, 22]. Уровень по умолчанию: 1.
Высокие уровни сжатия полезны в асимметричных сценариях, например когда данные сжимаются один раз, а распаковываются многократно. Чем выше уровень, тем лучше сжатие и тем выше нагрузка на CPU.
Устарело: ZSTD_QAT
Устарел: DEFLATE_QPL
Специализированные кодеки
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.
ALP
ALP() — адаптивное сжатие без потерь для данных с плавающей точкой на основе десятичного масштабирования. ALP пытается представить каждое значение как точное целое число, масштабированное степенями десяти, а затем сжимает полученные целые числа с помощью Frame-of-Reference и побитовой упаковки. Значения, которые нельзя представить точно, сохраняются как необработанные исключения. Лучше всего подходит для чисел, происходящих из десятичных значений (например, измерений или денежных сумм). Поддерживает Float32 и Float64. Подробности см. в статье ALP: Adaptive lossless floating-point compression.
Этот кодек является экспериментальным, и для его использования требуется
SET allow_experimental_codecs = 1.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 значений, помещает их в битовую матрицу 64x64, транспонирует ее, отбрасывает неиспользуемые биты значений и возвращает оставшуюся последовательность. Неиспользуемые биты — это биты, которые не различаются у максимального и минимального значений во всей части данных, для которой используется сжатие.
Кодеки DoubleDelta и Gorilla используются в Gorilla TSDB как части его алгоритма сжатия. Подход Gorilla эффективен в сценариях, где есть последовательность медленно меняющихся значений с соответствующими временными метками. Временные метки эффективно сжимаются кодеком DoubleDelta, а значения — кодеком Gorilla. Например, чтобы получить таблицу с эффективным хранением, можно создать ее в следующей конфигурации:
Кодеки шифрования
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 с ними в рамках одного сеанса.
- Временные таблицы исчезают после завершения сеанса, в том числе при потере соединения.
- Временная таблица использует движок таблицы Memory, если движок не указан, и может использовать любой движок таблицы, кроме Replicated и
KeeperMap. - Для временной таблицы нельзя указать БД. Она создаётся вне баз данных.
- Невозможно создать временную таблицу с помощью распределённого DDL-запроса на всех серверах кластера (с использованием
ON CLUSTER): такая таблица существует только в текущем сеансе. - Если временная таблица имеет то же имя, что и другая таблица, и в запросе указано имя таблицы без указания БД, будет использована временная таблица.
- При распределённой обработке запросов временные таблицы с движком Memory, используемые в запросе, передаются на удалённые серверы.
(GLOBAL) IN. Подробнее см. в соответствующих разделах
Вместо временных таблиц можно использовать таблицы с ENGINE = Memory.
REPLACE TABLE
REPLACE позволяет атомарно обновить таблицу атомарно.
Этот оператор поддерживается для движков баз данных
Atomic и Replicated,
которые являются движками баз данных по умолчанию для ClickHouse и ClickHouse Cloud соответственно.SELECT, который не выбирает нежелательные данные,
затем удалить старую таблицу и переименовать новую.
Этот подход показан в примере ниже:
REPLACE (при условии, что вы используете движки баз данных по умолчанию), чтобы добиться того же результата:
Синтаксис
Для этого оператора также применимы все синтаксические формы оператора
CREATE. Вызов REPLACE для несуществующей таблицы приведет к ошибке.Примеры:
- Локально
- Cloud
Рассмотрим следующую таблицу:Мы можем использовать оператор Или можно использовать оператор
REPLACE, чтобы удалить все данные:REPLACE, чтобы изменить структуру таблицы:Предложение COMMENT
Предложение
COMMENT должно быть указано после всех предложений, относящихся к хранилищу, таких как PARTITION BY, ORDER BY и SETTINGS, специфичных для хранилища.После предложения COMMENT будут разбираться только SETTINGS, относящиеся к запросу (например, max_threads и т. д.), а не настройки, связанные с хранилищем.Это означает, что правильный порядок предложений такой:ENGINE- предложения хранилища
COMMENT- настройки запроса (если есть)
Query
Response