Описание
pg_clickhouse — это расширение PostgreSQL, которое позволяет выполнять удалённые запросы к базам данных ClickHouse, в том числе через [обёртка сторонних данных]. Оно поддерживает PostgreSQL 14 и выше, а также ClickHouse 23.3 и выше.Начало работы
Проще всего попробовать pg_clickhouse с помощью [Docker-образа], который представляет собой стандартный Docker-образ PostgreSQL с расширениями pg_clickhouse и [re2][re2 extension]:Использование
Политика версионирования
pg_clickhouse придерживается Semantic Versioning для своих публичных релизов.- Основная версия увеличивается при изменениях API
- Дополнительная версия увеличивается при обратно совместимых изменениях SQL
- Номер патча увеличивается при изменениях только в бинарном файле
- Версия библиотеки (определяемая
PG_MODULE_MAGICв PostgreSQL 18 и выше) включает полную семантическую версию, которая видна в выводе функцииpgch_version()или функции Postgrespg_get_loaded_modules(). - Версия расширения (определяемая в control-файле) включает только основную
и дополнительную версии, которые видны в таблице
pg_catalog.pg_extension, в выводе функцииpg_available_extension_versions()и в\dx pg_clickhouse.
v0.1.0 до v0.1.1, приносит пользу всем базам данных, в которых загружена v0.1, и
не требует выполнения ALTER EXTENSION, чтобы воспользоваться обновлением.
С другой стороны, релиз, в котором увеличивается дополнительная или основная версия,
будет сопровождаться SQL-скриптами обновления, и все существующие базы данных, содержащие
расширение, должны выполнить ALTER EXTENSION pg_clickhouse UPDATE, чтобы воспользоваться
обновлением.
Справочник по SQL DDL
В следующих выражениях SQL DDL используется pg_clickhouse.CREATE EXTENSION
Используйте CREATE EXTENSION, чтобы добавить pg_clickhouse в базу данных:WITH SCHEMA, чтобы установить расширение в определённую схему (рекомендуется):
ALTER EXTENSION
Используйте ALTER EXTENSION, чтобы изменить pg_clickhouse. Примеры:-
После установки нового релиза pg_clickhouse используйте предложение
UPDATE: -
Используйте
SET SCHEMA, чтобы переместить расширение в новую схему:
DROP EXTENSION
Используйте DROP EXTENSION, чтобы удалить pg_clickhouse из базы данных:CASCADE, чтобы удалить и их:
CREATE SERVER
Используйте CREATE SERVER, чтобы создать внешний сервер, подключающийся к серверу ClickHouse. Пример:driver: драйвер подключения к ClickHouse: “binary” или “http”. Обязательный параметр.compression: сжатие native-протокола для драйвера “binary”: одно из значений “none”, “lz4” или “zstd”. По умолчанию — “lz4”. Для драйвера “http” не используется.dbname: база данных ClickHouse, используемая при подключении. По умолчанию — “default”.host: имя хоста сервера ClickHouse. По умолчанию — “localhost”;port: порт сервера ClickHouse, к которому нужно подключаться. Значения по умолчанию следующие:- 9440, если
driver— “binary” иhost— хост ClickHouse Cloud - 9004, если
driver— “binary” иhostне является хостом ClickHouse Cloud - 8443, если
driver— “http” иhost— хост ClickHouse Cloud - 8123, если
driver— “http” иhostне является хостом ClickHouse Cloud
- 9440, если
min_tls_version: минимальная версия протокола TLS, согласуемая при подключениях, использующих TLS. Одно из значений:TLSv1,TLSv1.1,TLSv1.2илиTLSv1.3. По умолчанию — минимальная версия, заданная в самой библиотеке TLS. Применяется к обоим драйверам.secure: управляет использованием TLS для подключения. Возможные значения:auto(по умолчанию): использовать TLS, еслиhost— хост ClickHouse Cloud илиport— защищенный порт; в противном случае — plaintext.on(илиtrue/yes/1): всегда использовать TLS. Значениеportпо умолчанию — 8443 (“http”) или 9440 (“binary”).off(илиfalse/no/0): никогда не использовать TLS. Значениеportпо умолчанию — 8123 (“http”) или 9000 (“binary”).
encoding_check: определяет, как обрабатывать символы, недопустимые в кодировке базы данных, при преобразовании значений ClickHouse типов String и JSON. Возможные значения:fail(по умолчанию): выдать ошибкуremoveудаляет недопустимые байтыreplace: в кодировке UTF-8 заменяет недопустимые байты символом замены Unicode (�); для других кодировок действует так же, какremovetruncateобрезает текст по первому недопустимому байту
ALTER SERVER
Используйте ALTER SERVER, чтобы изменить определение внешнего сервера. Пример:DROP SERVER
Чтобы удалить внешний сервер, используйте DROP SERVER:CASCADE, чтобы
также удалить эти зависимости:
CREATE USER MAPPING
Используйте CREATE USER MAPPING, чтобы сопоставить пользователя PostgreSQL с пользователем ClickHouse. Например, чтобы сопоставить текущего пользователя PostgreSQL с удалённым пользователем ClickHouse при подключении через внешний серверtaxi_srv:
user: Имя пользователя ClickHouse. По умолчанию — “default”.password: Пароль пользователя ClickHouse.
ALTER USER MAPPING
Используйте ALTER USER MAPPING, чтобы изменить определение пользовательского сопоставления:DROP USER MAPPING
Используйте DROP USER MAPPING, чтобы удалить пользовательское сопоставление:IMPORT FOREIGN SCHEMA
Используйте IMPORT FOREIGN SCHEMA, чтобы импортировать все таблицы, определённые в базе данных ClickHouse, в схему PostgreSQL как внешние таблицы:LIMIT TO, чтобы импортировать только указанные таблицы:
EXCEPT, чтобы исключить таблицы:
-
Импортированные столбцы сохраняют модификатор типа ClickHouse, в том числе
внутри
Array. Иначе говоря,Array(Decimal(12,6))импортируется какnumeric(12,6)[]. -
Столбцы
Nullableимпортируются безNOT NULL; наNullableвнутриArrayэто не распространяется, поскольку массивы PostgreSQL всегда допускают элементы NULL. -
Столбцы
AggregateFunctionиSimpleAggregateFunctionимпортируются безNOT NULLнезависимо от объявления в ClickHouse, см. Столбцы состояния иNOT NULL. -
Столбцы
Tupleимпортируются какtext[]. СтолбцыMapиNested, созданные сflatten_nested=0, импортируются какtext[][]. Каждое такое преобразование сопровождаетсяNOTICE. Псевдотипrecordв PostgreSQL нельзя использовать для определения столбца таблицы, поэтому каждый кортеж становится массивом значений, каждый map — двумерным массивом пар ключ-значение, а каждое значение Nested — двумерным массивом строк. Чтобы читать поля как записи, измените тип столбца на массив соответствующего составного типа; пример см. в разделе Ручное сопоставление типов. -
Столбцы
DateTime64иTime64с точностью более 6 (микросекунды) также вызываютNOTICE, поскольку в PostgreSQL точность ограниченаtimestamp(6)иtime(6). -
Типы столбцов, не имеющие аналога в PostgreSQL, включая устаревший тип
Object('json'), появившийся раньшеJSONв ClickHouse, приводят к ошибке.
CREATE FOREIGN TABLE
Используйте CREATE FOREIGN TABLE для создания внешней таблицы, позволяющей запрашивать данные из базы данных ClickHouse:database: Имя удалённой базы данных. По умолчанию используется база данных, заданная для внешнего сервера.table_name: Имя удалённой таблицы. По умолчанию используется имя, указанное для внешней таблицы.engine: [движок таблицы], используемый таблицей ClickHouse. ДляCollapsingMergeTree()иAggregatingMergeTree()pg_clickhouse автоматически применяет параметры к функциональным выражениям, выполняемым для таблицы.
-
column_name: Имя столбца на стороне ClickHouse, которое используется вместо имени атрибута PostgreSQL при генерации запросов и операций вставки. Это полезно для сопоставления имён столбцов PostgreSQL в нижнем регистре без кавычек со столбцами ClickHouse, чувствительными к регистру, например: -
AggregateFunction: Имя агрегатной функции, применяемой к столбцу типа AggregateFunction Type. Сопоставьте тип данных с типом ClickHouse, передаваемым в функцию, и укажите имя агрегатной функции через соответствующий параметр столбца; pg_clickhouse автоматически добавитMergeк агрегатной функции, вычисляющей этот столбец. Объявите столбец допускающим значения NULL, чтобы избежать проблем, описанных в разделе Столбцы состояний иNOT NULL. -
SimpleAggregateFunction: Имя агрегатной функции, применяемой к столбцу типа SimpleAggregateFunction Type. Сопоставьте тип данных с типом ClickHouse, передаваемым в функцию, и укажите имя агрегатной функции через соответствующий параметр столбца.
Столбцы состояний и NOT NULL
Столбцы AggregateFunction и SimpleAggregateFunction следует оставлять допускающими NULL.
Для столбцов состояний с NOT NULL PostgreSQL 19 заменяет count(column) на count(*),
и в результате подсчитываются строки, а не выполняется слияние состояний.
Рассмотрим таблицу ClickHouse, в которой хранится по одному состоянию count на пользователя, причём каждое состояние
построено на основе 1 000 событий:
NOT NULL PostgreSQL подсчитывает состояния, из-за чего результат подсчёта оказывается неверным:
NOT NULL pg_clickhouse использует countMerge() для слияния состояний и
возвращает правильное количество — 1000:
ALTER FOREIGN TABLE:
NOT NULL влияет только на PostgreSQL, поэтому IMPORT FOREIGN
SCHEMA импортирует столбцы состояния как допускающие NULL.
ALTER FOREIGN TABLE
Используйте ALTER FOREIGN TABLE, чтобы изменить описание внешней таблицы:DROP FOREIGN TABLE
Чтобы удалить внешнюю таблицу, используйте DROP FOREIGN TABLE:CASCADE:
Справочник по DML SQL
Приведённые ниже SQL-выражения DML могут использовать pg_clickhouse. В примерах ниже используются следующие таблицы ClickHouse:EXPLAIN
Команда EXPLAIN работает как ожидается, но параметрVERBOSE приводит к выводу запроса ClickHouse “Remote SQL”:
SELECT
Используйте оператор SELECT для выполнения запросов к таблицам pg_clickhouse, как и к любым другим таблицам:nodes и выполняем JOIN с ней вместо удалённой таблицы:
node_id вместо локального столбца, а затем выполнить JOIN
с таблицей lookup:
node_id, сокращая
число строк, которые нужно вернуть в Postgres, с 1000 (то есть
всех) до всего 8 — по одной на каждый узел.
Партиционированные таблицы
[Партиционированная таблица] PostgreSQL может сочетать локальные партиции с внешними партициями, размещёнными в ClickHouse. Распространённая структура предполагает перенос старых данных в ClickHouse, тогда как новые данные остаются в PostgreSQL:enable_partitionwise_aggregate PostgreSQL вычисляет частичный
агрегат под Append, а затем завершающий агрегат над ним объединяет эти
частичные результаты. pg_clickhouse передаёт частичный агрегат внешней партиции
в ClickHouse:
Когда выполняется проталкивание частичных агрегатов
PostgreSQL представляет частичный агрегат в виде переходного состояния, которое на этапе завершения объединяется по всем партициям. pg_clickhouse может протолкнуть частичное состояние партиции, только если его можно представить в виде значения ClickHouse:- Декомпозируемые агрегаты, у которых переходное состояние уже является итоговым
значением, проталкиваются напрямую:
count,sum,min,max,bool_and/every,bool_or,bit_and,bit_orиbit_xor. avgдля целых чисел проталкивает состояние{count, sum}в виде массива.avg,var_pop,var_samp,stddev_popиstddev_sampдля чисел с плавающей запятой проталкивают состояние{N, sum, sum of squared deviations}в виде массива.
FILTER (WHERE …) проталкивается вместе с этими агрегатными функциями.
Когда используется локальная обработка
Агрегатные функции, состояние перехода которых имеет непрозрачный тип PostgreSQLinternal,
не имеют переносимого представления, поэтому внешняя партиция вместо этого загружает свои строки
и выполняет агрегацию локально. Это относится ко всем агрегатам для numeric, а также к
avg(bigint) и avg(interval). Агрегаты DISTINCT, упорядоченных множеств и вариативные
агрегаты также используют локальную обработку.
PREPARE, EXECUTE, DEALLOCATE
Начиная с версии v0.1.2, pg_clickhouse поддерживает параметризованные запросы, которые в основном создаются с помощью команды PREPARE:{param:type}:
INSERT
Используйте команду INSERT, чтобы вставить значения в удалённую таблицу ClickHouse:COPY
Используйте команду COPY, чтобы выполнить вставку батча строк в удалённую таблицу ClickHouse:⚠️ Ограничения Batch API В pg_clickhouse пока не реализована поддержка Batch API вставки PostgreSQL FDW. Поэтому COPY сейчас использует операторы INSERT для вставки записей. Это будет исправлено в одном из будущих релизов.
LOAD
С помощью LOAD загрузите разделяемую библиотеку pg_clickhouse:SET
Используйте SET, чтобы установить пользовательские параметры конфигурации pg_clickhouse.pg_clickhouse.session_settings
Параметр pg_clickhouse.session_settings задаёт [настройки ClickHouse],
которые будут применяться к последующим запросам. Пример:
join_use_nulls для внешних JOIN и transform_null_in для семейства IN
(см. IN и семантика NULL).
date_time_output_format: HTTP-драйвер требует, чтобы значение было “iso”format_tsv_null_representation: HTTP-драйвер требует значение по умолчаниюoutput_format_tsv_crlf_end_of_lineHTTP-драйвер требует значение по умолчанию
pg_clickhouse.session_settings; для этого либо используйте [предварительную загрузку разделяемой библиотеки], либо
просто воспользуйтесь одним из объектов в расширении, чтобы гарантировать его загрузку.
pg_clickhouse.pushdown_regex
Параметр pg_clickhouse.pushdown_regex определяет, будет ли pg_clickhouse
выполнять pushdown функций и операторов регулярных выражений. По умолчанию это включено;
установите для этого параметра значение false, чтобы отключить pushdown для них:
ALTER ROLE
Используйте командуSET оператора ALTER ROLE для предварительной загрузки pg_clickhouse
и/или для установки его параметров для определённых ролей:
RESET оператора ALTER ROLE, чтобы сбросить предварительную загрузку pg_clickhouse
и/или его параметры:
Предварительная загрузка
Если pg_clickhouse нужен для всех или почти всех подключений Postgres, рассмотрите [предварительную загрузку разделяемой библиотеки], чтобы она загружалась автоматически:session_preload_libraries
Загружает разделяемую библиотеку при каждом новом подключении к PostgreSQL:
shared_preload_libraries
Загружает разделяемую библиотеку в родительский процесс PostgreSQL при запуске:
Типы данных
В этой таблице приведено рекомендуемое сопоставление типов данных ClickHouse и PostgreSQL. IMPORT FOREIGN SCHEMA использует эти сопоставления и выводит соответствующие модификаторы типов и размерности массивов. Чтобы объявить альтернативные типы PostgreSQL, используйте CREATE FOREIGN TABLE. В столбце дополнительных целевых типов для чтения перечислены преобразования, которые драйверbinary поддерживает помимо
явных приведений PostgreSQL. Пустая ячейка не означает, что такие приведения запрещены. Значения должны
помещаться в целевые типы. Эти целевые типы относятся только к чтению; для записи действуют отдельные
правила преобразования.
Любой столбец также можно прочитать как
text, varchar или другой строковый тип. Значение
сначала приводится к указанному выше типу PostgreSQL, а затем выводится через функцию вывода
этого типа. Строка ClickHouse, прочитанная как текстовый тип, проверяется на соответствие
кодировке базы данных, поэтому байты, которые PostgreSQL не может прочитать, приводят к ошибке. Объявите
столбец String, FixedString, Enum или JSON как BYTEA, чтобы читать его байты в том виде, в каком
их записал ClickHouse.
Типы, совместимые по вводу, могут читать строки с помощью своей функции ввода PostgreSQL.
Поля составных типов должны совпадать как по составу, так и по порядку. Чтобы прочитать Tuple
как массив, каждое поле должно преобразовываться в тип элемента массива, и ни одно поле
не может само быть массивом.
При чтении в виде массивов Map даёт по одной строке на каждую пару ключ-значение, а Nested —
по одной строке на каждую вложенную запись. Чтобы прочитать Tuple как box, укажите две точки; для
circle — точку и радиус; для line — три коэффициента.
Далее приведены дополнительные примечания и подробности.
Приведение типов
При использовании драйвераbinary альтернативные скалярные типы преобразуются с помощью явных
приведений PostgreSQL (если они доступны), а элементы массивов приводятся к объявленному
типу элементов. Неподдерживаемые преобразования и значения, выходящие за допустимый диапазон, приводят к ошибкам.
С любым из драйверов типы ClickHouse Interval можно сопоставить с smallint, integer
или bigint, чтобы читать и записывать количество соответствующих единиц. Например, значение
IntervalDay, равное 3, сопоставляется с целым числом 3. При сопоставлении
IntervalNanosecond с bigint наносекунды сохраняются, а при сопоставлении с
interval значение усекается до микросекунд.
BYTEA
ClickHouse не предоставляет эквивалента типа PostgreSQL BYTEA, однако позволяет хранить произвольные байты в типе [String]. В общем случае строки ClickHouse следует сопоставлять с типом PostgreSQL [TEXT], но при работе с двоичными данными используйте тип BYTEA. Пример:SELECT выведет:
FixedString(N) дополняет короткие значения нулевыми байтами. Текстовый столбец
отбрасывает эти завершающие нулевые байты, тогда как столбец BYTEA сохраняет каждый байт.
Составные типы
Array
Тип [Array] в ClickHouse напрямую сопоставляется с массивами PostgreSQL с эквивалентной семантикой. Основное отличие в том, что в многомерных массивах Postgres вложенные выражения массивов должны иметь одинаковую размерность. Попытка прочитать массив ClickHouse с разной размерностью, например[[1], [2,3]],
приводит к ошибке.
Доступ к элементам массива по индексу проталкивается в удалённую систему там, где это возможно, включая доступ по индексу
в многомерных массивах. Примеры:
Map
В PostgreSQL нет типа, соответствующего типу ClickHouse [Map]. Поэтому pg_clickhouse отображает столбцы [Map] вtext[][], где каждая пара ключ-значение
представлена отдельным массивом. Именно это отображение использует IMPORT FOREIGN SCHEMA.
Значения Map также можно вставлять с помощью INSERT в виде массивов. Пример:
Для вставки
Map требуется драйвер binary, который получает типы столбцов
от сервера ClickHouse. Драйвер http этого не делает, поэтому ему недостаточно
информации, чтобы отформатировать и вставить нужное значение.Tuple
Аналогичным образом столбцы ClickHouse типа [Tuple] отображаются вtext[] и поддерживают INSERT
через драйвер binary. При таком отображении IMPORT FOREIGN SCHEMA выдаёт
NOTICE.
Nested
По умолчанию ClickHouse разбивает столбецNested на отдельные столбцы Array — по одному на каждое
поле (flatten_nested=1). IMPORT FOREIGN SCHEMA считывает их из
каталога ClickHouse system.columns и создаёт отдельные столбцы-массивы PostgreSQL,
сохраняя имена с точкой, например items.a и items.b. Например,
для следующей внешней таблицы:
WHERE с помощью стандартных возможностей массивов,
включая синтаксис обращения к элементам по индексу:
flatten_nested=0, отображается в массив, в котором каждой
вложенной строке соответствует один элемент. Каждый элемент массива содержит значения этой строки:
c2 Nested(id Int64, name String) из этого примера это будет выглядеть так:
text[][] в типы Nested завершается ошибкой:
Ручное сопоставление типов
IMPORT FOREIGN SCHEMA использует универсальные типы PostgreSQL. Например,
возьмём таблицу ClickHouse со столбцами типов [Enum], [Tuple], Map и неуплощённого
[Nested] (flatten_nested = 0), такую как:
key и value).
Nested и Map превращаются в массивы составных значений, а Tuple —
в одно составное значение:
SELECT:
WHERE — при условии, что имена полей
совпадают:
INSERT с использованием таких составных типов пока не поддерживается.
Справочник по Function и операторам
Функции
Эти функции служат интерфейсом для выполнения запросов к базе данных ClickHouse.clickhouse_server_version
major.minor.patch для указанного
стороннего сервера, при необходимости подключаясь с использованием параметров сервера и
пользовательского сопоставления текущего пользователя:
SELECT version() и кэширует её на весь срок
жизни соединения.
clickhouse_query
driver сервера,
учётные данные, базу данных и кэш подключений.
Первый аргумент — имя сервера, созданного с помощью CREATE SERVER. Требуется
список определений столбцов (AS name(col type, ...)): PostgreSQL необходимо
знать структуру результата до получения строк, и она должна соответствовать столбцам, которые возвращает запрос. Значения преобразуются из ClickHouse в объявленные типы так же,
как для столбца внешней таблицы. Операторам, не возвращающим результаты, например DDL,
нечего объявлять; вместо этого выполняйте их с помощью
clickhouse_perform.
По умолчанию ни одна роль не имеет права EXECUTE; предоставьте его роли, чтобы разрешить ей использовать
функцию.
clickhouse_perform
clickhouse_query не имеет формы результата, которую можно объявить. Он
разрешает сервер так же, как clickhouse_query, повторно используя его
driver, учётные данные, базу данных и кэш подключений.
Как процедуру его следует вызывать с помощью CALL, а не SELECT; он не возвращает
строк. По умолчанию ни у одной роли нет права EXECUTE; предоставьте его роли с помощью GRANT, чтобы она могла
использовать процедуру.
Функции с pushdown
pg_clickhouse выполняет pushdown для части встроенных функций PostgreSQL, используемых в условных выражениях (в секцияхHAVING и WHERE). Для них используются следующие
эквиваленты в ClickHouse:
abs: absfactorial: factorialmod(int2/int4/int8/numeric): остаток от деленияpow&power(float8, но не numeric): powround: roundsin,cos,tan,atan,atan2,sinh,cosh,tanh,asinh,degrees,radians,pi: математические функции ClickHouse с такими же именами. Дляasin,acos,atanh,acoshpushdown не применяется: PG выдаёт ошибку для входных данных вне диапазона, тогда как CH возвращаетNaN.date_part:date_part('day'): toDayOfMonthdate_part('doy'): toDayOfYeardate_part('dow'): toDayOfWeekdate_part('year'): toYeardate_part('month'): toMonthdate_part('hour'): toHourdate_part('minute'): toMinutedate_part('second'): toSeconddate_part('quarter'): toQuarterdate_part('isoyear'): toISOYeardate_part('week'): toISOYeardate_part('epoch'): toISOYear
date_trunc:date_trunc('week'): toMondaydate_trunc('second'): toStartOfSeconddate_trunc('minute'): toStartOfMinutedate_trunc('hour'): toStartOfHourdate_trunc('day'): toStartOfDaydate_trunc('month'): toStartOfMonthdate_trunc('quarter'): toStartOfQuarterdate_trunc('year'): toStartOfYear
extract(field FROM source): такие же соответствия, как уdate_partdate(timestamp)&date(timestamptz): toDate (при обратном преобразовании как алиас CHdate)array_position: indexOf с nullIf для преобразования0вNULLи arraySlice при наличии третьего аргумента, задающего начальный индекс поиска; обратите внимание, чтоnanпока не сопоставляетсяarray_cat: arrayConcatarray_append: arrayPushBackarray_prepend: arrayPushFrontarray_remove: arrayRemovecardinality: arrayFlattenedLength в ClickHouse 26.9+, в остальных случаях — length, которая учитывает только внешний массивarray_length(array, 1):nullIf(length(array), 0)array_length&cardinality: длинаarray_to_string: arrayStringConcatstring_to_array: splitByStringsplit_part: splitByString + индексация массиваtrim_array: arrayResizearray_fill: arrayWithConstantarray_reverse: arrayReversearray_shuffle: arrayShufflearray_sample: arrayRandomSamplearray_sort: arraySort / arrayReverseSortbtrim: trimBothltrim: trimLeftrtrim: trimRightconcat_ws: concatWithSeparatorlower(text): lowerUTF8upper(text): upperUTF8substring(text, ...)&substr(text, ...): substringUTF8substring(bytea, ...)&substr(bytea, ...): substringlength(text): lengthUTF8length(bytea)&octet_length: lengthreverse(text): reverseUTF8reverse(bytea): reversestrpos: positionUTF8regexp_like: matchregexp_match: extractGroups если регулярное выражение содержит подвыражения в скобках; в противном случае extractAll со срезом через arraySlice.regexp_replace: replaceRegexpOne или replaceRegexpOne при наличии флагаgregexp_split_to_array: splitByRegexpmd5: MD5sha224,sha256,sha384иsha512: соответствующие функции SHA в ClickHouseencode(bytea, fmt), еслиfmt— строковая константа (регистронезависимая):encode(bytea, 'hex'): hex обёрнутая в lower, поскольку PostgreSQL выводит hex в нижнем регистре.encode(bytea, 'base64'): base64Encode обёрнутая в replaceRegexpAll для воспроизведения разрыва строки MIME (RFC 2045), вставляемого PostgreSQL через каждые 76 символов.encode(bytea, 'base64url')(PostgreSQL 19+): base64URLEncode, которая соответствует URL-алфавиту RFC 4648 PostgreSQL без дополнения.
json_extract_path_text: синтаксис подстолбцовjson_extract_path: toJSONString + синтаксис подстолбцовjsonb_extract_path_text: синтаксис подстолбцовjsonb_extract_path: toJSONString + синтаксис обращения к подстолбцамbit_count(bytea): bitCountto_timestamp(float8): toDateTime64to_char(timestamp[tz], fmt): formatDateTime еслиfmt— это строковая константа, для каждого ключевого слова которой есть точный эквивалент в ClickHouse. Поддерживаемые ключевые слова см. в to_char() в разделе «Примечания по совместимости». В противном случае функция выполняется локально в PostgreSQL.statement_timestamp,transaction_timestamp, &clock_timestamp: nowInBlock64 (nowInBlock64(9, $session_timezone))CURRENT_DATE: now и toDate (toDate(now($session_timezone)))now,CURRENT_TIMESTAMP, &LOCALTIMESTAMP: now64 (now64(9, $session_timezone))CURRENT_TIMESTAMP(n)&LOCALTIMESTAMP(n): now64 (now64(n, $session_timezone))CURRENT_DATABASE: Передаётся в качестве значения из функции PostgreSQL.CURRENT_SCHEMA: Передаётся как значение из функции PostgreSQL.CURRENT_CATALOG: Передаётся как значение из функции PostgreSQL.CURRENT_USER: Передаётся в качестве значения из функции PostgreSQL.USER: передаётся в качестве значения из функции PostgreSQL.CURRENT_ROLE: Передаётся как значение из функции PostgreSQL.SESSION_USER: Передаётся как значение, возвращаемое функцией PostgreSQL.
Операторы pushdown
- Срез массива (
arr[L:U]): arraySlice @>(массив содержит): hasAll<@(массив содержится в): hasAll&&(массивы пересекаются): hasAny~(совпадение с регулярным выражением): match!~(нет совпадения с регулярным выражением): match~*(регистронезависимое отсутствие совпадения с регулярным выражением): match!~*(регистронезависимое отсутствие совпадения с регулярным выражением): match->>(извлечение элемента JSON/JSONB как текста): синтаксис подстолбцов->(извлечение JSON/JSONB): toJSONString + синтаксис подстолбцов
Семантика IN и NULL
ClickHouse вычисляетIN в рамках двузначной логики: если проверяемое значение не находит
совпадений, возвращается 0, даже если участвует NULL, тогда как PostgreSQL возвращает
NULL. Чтобы сохранить семантику PostgreSQL, pg_clickhouse безусловно проталкивает семейство
IN для списка констант или массива (IN, NOT IN, = ANY, = ALL, <> ANY, <> ALL): нативную или недорогую форму, когда можно
доказать, что ни проверяемое значение, ни элемент массива не могут быть NULL, либо защищённую
форму CASE в остальных случаях, которая вместо этого проверяет NULL во время выполнения,
вычисляя точный трёхзначный результат PostgreSQL (TRUE, FALSE, NULL) в
любом контексте, включая позиции значений, например в списке SELECT или
GROUP BY.
Фильтр NOT IN (SELECT ...) по столбцам с типом Nullable также проталкивается;
при обратном преобразовании добавляются компенсирующие проверки, сохраняющие поведение PostgreSQL:
множество, содержащее NULL, исключает каждую строку, а NULL в проверяемом значении проходит только
при сравнении с пустым множеством. Каждая проверка опускается, если объявление NOT NULL
доказывает её ненужность. В отличие от форм с массивами выше, эта проверка применяется только
в простом условии фильтрации (или под NOT); IN (SELECT ...) (в позиции значения) и тела
сгруппированных или агрегированных подзапросов по-прежнему не поддерживают pushdown.
Объявление столбцов как NOT NULL максимально расширяет возможности pushdown, позволяя вместо этого
отправлять более дешёвую форму без проверок; IMPORT FOREIGN SCHEMA делает это автоматически для
столбцов ClickHouse без типа Nullable. При доказательстве учитываются константы, отличные от NULL,
столбцы NOT NULL и базовая арифметика (+, -, *, унарный -) над ними.
Эти правила предполагают, что в ClickHouse используется значение по умолчанию transform_null_in = 0, которое
pg_clickhouse задаёт для каждого запроса через значение по умолчанию
параметра pg_clickhouse.session_settings,
чтобы профиль сервера ClickHouse не мог незаметно его изменить. Установка
transform_null_in = 1 нарушает семантику каждого IN, для которого выполняется pushdown.
Пользовательские функции
Эти пользовательские функции, созданные pg_clickhouse, обеспечивают pushdown внешних запросов для некоторых функций ClickHouse, у которых нет аналогов в PostgreSQL. Если какую-либо из этих функций не удастся выполнить через pushdown, будет вызвано исключение.Pushdown для расширений
pg_clickhouse распознает функции некоторых основных и сторонних расширений и передает их на pushdown к их эквивалентам в ClickHouse.re2
Все операторы и функции [расширения re2] проталкиваются в ClickHouse в соотношении 1:1:@~→ matchre2match→ matchre2extract→ extractre2extractall→ extractAllre2regexpextract→ regexpExtractre2extractgroups→ extractGroupsre2replaceregexpone→ replaceRegexpOnere2replaceregexpall→ replaceRegexpAllre2countmatches→ countMatchesre2countmatchescaseinsensitive→ countMatchesCaseInsensitivere2multimatchany→ multiMatchAnyre2multimatchanyindex→ multiMatchAnyIndexre2multimatchallindices→ multiMatchAllIndices
intarray
Одна функция [intarray] выполняется в ClickHouse:idx→ indexOf
fuzzystrmatch
В ClickHouse проталкиваются две функции [fuzzystrmatch]:soundex: soundexlevenshtein(с двумя аргументами): editDistanceUTF8
pgcyrpto
digest(text, text)иdigest(bytea, text): соответствующая хеш-функция ClickHouse, если алгоритм задан константойmd5,sha1,sha224,sha256,sha384илиsha512(без учёта регистра).
Приведения типов с pushdown
pg_clickhouse выполняет pushdown для приведений типов, таких какCAST(x AS bigint), если
типы данных совместимы. Для несовместимых типов pushdown завершится ошибкой; если x в этом
примере имеет тип ClickHouse UInt64, ClickHouse откажется приводить это значение.
Чтобы выполнять pushdown приведений к несовместимым типам данных, pg_clickhouse предоставляет
следующие функции. Они вызывают исключение в PostgreSQL, если pushdown не выполняется.
Агрегатные функции с pushdown
Для этих агрегатных функций PostgreSQL поддерживается pushdown в ClickHouse.- any_value
- array_agg
- avg
- bit_and
- bit_or
- bit_xor
- bool_and / every
- bool_or
- count
- corr
- covarpop
- covarsamp
- min
- max
- stddev_pop
- stddev_samp / stddev
- string_agg
- sum
- var_op
- var_samp /variance
Пользовательские агрегаты
Эти пользовательские агрегатные функции, созданные в pg_clickhouse, обеспечивают pushdown внешних запросов для некоторых агрегатных функций ClickHouse, не имеющих эквивалентов в PostgreSQL. Если какую-либо из этих функций невозможно передать через pushdown, будет вызвано исключение.Pushdown для агрегатных функций ordered set
Эти [агрегатные функции ordered set] сопоставляются с [параметрическими агрегатными функциями] ClickHouse путём передачи их непосредственного аргумента в качестве параметра, а выраженийORDER BY — в качестве аргументов. Например, следующий запрос PostgreSQL:
ORDER BY — DESC и NULLS FIRST —
не поддерживаются и вызовут ошибку.
percentile_cont(double): quantilepercentile_cont(double[]): quantilespercentile_disc(double): quantileExactLowpercentile_disc(double[]): quantilesExactLow
Пользовательская агрегатная функция ordered set
Эти пользовательские [агрегатные функции ordered set], созданные pg_clickhouse, обеспечивают pushdown внешних запросов для некоторых [параметрических агрегатных функций] ClickHouse. Если какую-либо из этих функций не удаётся выполнить с pushdown, будет вызвано исключение.quantile(double): quantilequantileExact(double): quantileExact
Пользовательские агрегатные функции ordered set
Эти пользовательские [агрегатные функции ordered set], созданные pg_clickhouse, поддерживают pushdown внешних запросов для отдельных параметрических [агрегатных функций] ClickHouse. Если любую из этих функций нельзя выполнить с pushdown, будет вызвано исключение.Оконные функции с pushdown
Эти [оконные функции] PostgreSQL проталкиваются в ClickHouse с секциямиOVER (PARTITION BY ... ORDER BY ...), включая спецификации рамки окна, где
это применимо.
- row_number
- rank
- dense_rank
- ntile
- cume_dist
- percent_rank
- lead
- lag
- first_value
- last_value
- nth_value
min/max(с секциейOVER)
row_number, rank, dense_rank, ntile, cume_dist,
percent_rank) не включают секцию рамки окна, поскольку ClickHouse
не поддерживает спецификации рамки окна для этих функций.
Примечания по совместимости
Регулярные выражения
Хотя pg_clickhouse выполняет pushdown регулярных выражений в эквиваленты ClickHouse, когда pg_clickhouse.pushdown_regex имеет значение true (по умолчанию), и старается обеспечить базовый уровень совместимости, важно учитывать различия между ними и то, как pg_clickhouse их обрабатывает.-
PostgreSQL поддерживает [регулярные выражения POSIX], а ClickHouse —
[регулярные выражения RE2][RE2]. Учитывайте различия в их поведении: используйте RE2,
если регулярное выражение будет обрабатываться в ClickHouse (например, в
предложении
WHERE), и POSIX, если оно будет обрабатываться в Postgres (например, в предложенииSELECT). -
pg_clickhouse проталкивает [флаги Postgres], добавляя их в начало
регулярного выражения ClickHouse внутри
(?). Например:Преобразуется в -
Единственные флаги, которые поддерживаются в обоих вариантах и потому могут использоваться при обработке в
ClickHouse:
RE2 поддерживает только эти флаги; не используйте другие [флаги Postgres].
-
В этой таблице приведено краткое описание влияния различных флагов (а также отсутствия флага, что
эквивалентно
s) на сопоставление символов новой строки и концов строк. Обратите внимание, что в Postgres флагиmиpне позволяют отрицательным символьным классам ([^xyz]) сопоставляться с символом новой строки, тогда как их аналоги в ClickHouse это ограничение не вводят. В остальном поведение ClickHouse такое же, как в Postgres: - Любые другие флаги, передаваемые функциям регулярных выражений, будут препятствовать pushdown функции.
-
Исключение —
regexp_replace(), которая также поддерживает флагg. Когда заданg, pg_clickhouse используетreplaceRegexpAll()вместоreplaceRegexpOne()и удаляет этот флаг перед добавлением остальных флагов. -
Аргумент replacement в Postgres
regexp_replace()поддерживает\&для ссылки на всё совпадение, тогда как в ClickHouse для ссылки на всё совпадение используется\0. Обязательно используйте\0, когда функция проталкивается в ClickHouse. -
Postgres
regexp_matchвозвращаетNULL, если совпадений нет, тогда как проталкиваемые выражения возвращают пустой массив. ИспользуйтеCOALESCE(), чтобы вместоNULLвозвращать пустой массив и тем самым сравнивать возвращаемые значения единообразно. Например:
to_char()
PostgreSQL [to_char()] для timestamp и timestamp with time zone
проталкивается в ClickHouse [formatDateTime] только в том случае, если аргумент format
— это строковая константа, не равная NULL, и каждому ключевому слову PostgreSQL в ней
соответствует побайтно идентичный эквивалент в ClickHouse. Если формат задаётся динамически
или содержит неподдерживаемое ключевое слово либо модификатор,
вызов переключается на локальное вычисление в PostgreSQL. pg_clickhouse никогда
не проталкивает частичный перевод, поэтому вывод остаётся совместимым.
Формы to_char() с двумя аргументами для numeric, interval и других
нетемпоральных типов никогда не проталкиваются; ClickHouse [formatDateTime] форматирует только
значения даты и времени.
Преобразованные ключевые слова
Текст в кавычках и литералы
Текст, заключённый в"...", передаётся как есть; при этом любой символ %
удваивается до %%, чтобы экранировать префикс спецификатора ClickHouse. Последовательность \" вне
кавычек также передаётся как литеральный ". Внутри "..." обратная косая черта
экранирует только "; другие последовательности с обратной косой чертой трактуются как литеральный текст.
Авторы
David E. WheelerАвторские права
Авторские права (c) 2025-2026, ClickHouse [Array] https://clickhouse.com/docs/reference/data-types/array “Документация ClickHouse: Array(T)” [Map]: https://clickhouse.com/docs/sql-reference/data-types/map “Документация ClickHouse: Map” [Tuple]: https://clickhouse.com/docs/reference/data-types/tuple “Документация ClickHouse: Tuple(T1, T2, …)” [Nested]: https://clickhouse.com/docs/sql-reference/data-types/nested-data-structures/nested “Документация ClickHouse: Nested” [Enum]: https://clickhouse.com/docs/reference/data-types/enum “Документация ClickHouse: Enum” [String]: /reference/data-types/string “Документация ClickHouse: String” [TEXT]: https://www.postgresql.org/docs/current/datatype-character.html “Документация PostgreSQL: символьные типы” [оконная функция]: https://www.postgresql.org/docs/current/functions-window.html “Документация PostgreSQL: оконные функции” [POSIX Regular Expressions]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-POSIX-REGEXP “Документация PostgreSQL: регулярные выражения POSIX” [Postgres flags]: https://www.postgresql.org/docs/current/functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE “Документация PostgreSQL: буквы встроенных опций ARE” [RE2]: https://github.com/google/re2/wiki/Syntax “Синтаксис RE2” [расширение re2]: https://github.com/ClickHouse/pg_re2 “pg_re2: совместимые с ClickHouse функции регулярных выражений на основе RE2” [intarray]: https://www.postgresql.org/docs/current/intarray.html “Документация PostgreSQL: intarray” [fuzzystrmatch]: https://www.postgresql.org/docs/current/fuzzystrmatch.html “Документация PostgreSQL: fuzzystrmatch” [to_char()]: https://www.postgresql.org/docs/current/functions-formatting.html “Документация PostgreSQL: функции форматирования типов данных”
[formatDateTime]: /reference/functions/regular-functions/date-time-functions#formatDateTime “Документация ClickHouse: formatDateTime”