Dynamic type, use the following syntax:
N is an optional parameter between 0 and 254 indicating how many different data types can be stored as separate subcolumns inside a column with type Dynamic across single block of data that is stored separately (for example across single data part for MergeTree table). If this limit is exceeded, all values with new types will be stored together in a special shared data structure in binary form. Default value of max_types is 32.
Creating Dynamic
UsingDynamic type in table column definition:
Variant column:
Reading Dynamic nested types as subcolumns
Dynamic type supports reading a single nested type from a Dynamic column using the type name as a subcolumn.
So, if you have column d Dynamic you can read a subcolumn of any valid type T using syntax d.T,
this subcolumn will have type Nullable(T) if T can be inside Nullable and T otherwise. This subcolumn will
be the same size as original Dynamic column and will contain NULL values (or empty values if T cannot be inside Nullable)
in all rows in which original Dynamic column doesn’t have type T.
Dynamic subcolumns can be also read using function dynamicElement(dynamic_column, type_name).
Examples:
dynamicType(dynamic_column) can be used. It returns String with value type name for each row (or 'None' if row is NULL).
Example:
Conversion between Dynamic column and other columns
There are 4 possible conversions that can be performed withDynamic column.
Converting an ordinary column to a Dynamic column
Converting a String column to a Dynamic column through parsing
To parseDynamic type values from a String column you can enable setting cast_string_to_dynamic_use_inference:
Converting a Dynamic column to an ordinary column
It is possible to convert aDynamic column to an ordinary column. In this case all nested types will be converted to a destination type:
Converting a Variant column to Dynamic column
Converting a Dynamic(max_types=N) column to another Dynamic(max_types=K)
IfK >= N than during conversion the data doesn’t change:
K < N, then the values with the rarest types will be inserted into a single special subcolumn, but still will be accessible:
isDynamicElementInSharedData returns true for rows that are stored in a special shared data structure inside Dynamic and as we can see, resulting column contains only 2 types that are not stored in shared data structure.
If K=0, all types will be inserted into single special subcolumn:
Reading Dynamic type from the data
All text formats (TSV, CSV, CustomSeparated, Values, JSONEachRow, etc) supports readingDynamic type. During data parsing ClickHouse tries to infer the type of each value and use it during insertion to Dynamic column.
Example:
Using Dynamic type in functions
Most of the functions support arguments with typeDynamic. In this case the function is executed separately on each internal data type stored inside Dynamic column.
When the result type of the function depends on the arguments types, the result of such function executed with Dynamic arguments will be Dynamic. When the result type of the function doesn’t depend on the arguments types - the result will be Nullable(T) where T the usual result type of this function.
Examples:
Dynamic column, the exception will be thrown:
Type mismatch behavior
The settingdynamic_throw_on_type_mismatch controls what happens when a function is applied to a Dynamic column and the actual stored type of a row is incompatible with the function:
true(default) — throw an exception (ILLEGAL_TYPE_OF_ARGUMENT) on the first incompatible row.false— returnNULLfor incompatible rows and keep the result for compatible rows.
Using Dynamic type in ORDER BY and GROUP BY
DuringORDER BY and GROUP BY values of Dynamic types are compared similar to values of Variant type:
The result of operator < for values d1 with underlying type T1 and d2 with underlying type T2 of a type Dynamic is defined as follows:
- If
T1 = T2 = T, the result will bed1.T < d2.T(underlying values will be compared). - If
T1 != T2, the result will beT1 < T2(type names will be compared).
Dynamic type is not allowed in GROUP BY/ORDER BY keys, if you want to use it consider its special comparison rule and enable allow_suspicious_types_in_group_by/allow_suspicious_types_in_order_by settings.
Examples:
</>/= and others because of special work of functions with Dynamic type
Reaching the limit in number of different data types stored inside Dynamic
Dynamic data type can store only limited number of different data types as separate subcolumns. By default, this limit is 32, but you can change it in type declaration using syntax Dynamic(max_types=N) where N is between 0 and 254 (due to implementation details, it’s impossible to have more than 254 different data types that can be stored as separate subcolumns inside Dynamic).
When the limit is reached, all new data types inserted to Dynamic column will be inserted into a single shared data structure that stores values with different data types in binary form.
Let’s see what happens when the limit is reached in different scenarios.
Reaching the limit during data parsing
During parsing ofDynamic values from the data, when the limit is reached for current block of data, all new values will be inserted into shared data structure:
Int64, Array(Int64) and String all new types were inserted into special shared data structure.
During merges of data parts in MergeTree table engines
During merge of several data parts in MergeTree table theDynamic column in the resulting data part can reach the limit of different data types that can be stored in separate subcolumns inside and won’t be able to store all types as subcolumns from source parts.
In this case ClickHouse chooses what types will remain as separate subcolumns after merge and what types will be inserted into shared data structure. In most cases ClickHouse tries to keep the most frequent types and store the rarest types in shared data structure, but it depends on the implementation.
Let’s see an example of such merge. First, let’s create a table with Dynamic column, set the limit of different data types to 3 and insert values with 5 different types:
Dynamic column containing single type:
UInt64 and Array(UInt64) as subcolumns and inserted all other types into shared data.
JSONExtract functions with Dynamic
AllJSONExtract* functions support Dynamic type:
Binary output format
In RowBinary format values ofDynamic type are serialized in the following format: