Skip to main content

Описание

pg_clickhouse — это расширение PostgreSQL, которое позволяет выполнять удалённые запросы к базам данных ClickHouse, в том числе через [обёртка сторонних данных]. Оно поддерживает PostgreSQL 14 и выше, а также ClickHouse 23.3 и выше.

Начало работы

Проще всего попробовать pg_clickhouse с помощью [Docker-образа], который представляет собой стандартный Docker-образ PostgreSQL с расширениями pg_clickhouse и [re2][re2 extension]:
См. руководство, чтобы узнать, как импортировать таблицы ClickHouse и делегировать выполнение запросов.

Использование

Политика версионирования

pg_clickhouse придерживается Semantic Versioning для своих публичных релизов.
  • Основная версия увеличивается при изменениях API
  • Дополнительная версия увеличивается при обратно совместимых изменениях SQL
  • Номер патча увеличивается при изменениях только в бинарном файле
После установки PostgreSQL отслеживает два варианта версии:
  • Версия библиотеки (определяемая PG_MODULE_MAGIC в PostgreSQL 18 и выше) включает полную семантическую версию, которая видна в выводе функции pgch_version() или функции Postgres pg_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 из базы данных:
Эта команда завершится ошибкой, если от 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
  • 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 (�); для других кодировок действует так же, как remove
    • truncate обрезает текст по первому недопустимому байту

ALTER SERVER

Используйте ALTER SERVER, чтобы изменить определение внешнего сервера. Пример:
Параметры те же, что и для CREATE 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, чтобы изменить определение пользовательского сопоставления:
Параметры такие же, как для CREATE USER MAPPING.

DROP USER MAPPING

Используйте DROP USER MAPPING, чтобы удалить пользовательское сопоставление:

IMPORT FOREIGN SCHEMA

Используйте IMPORT FOREIGN SCHEMA, чтобы импортировать все таблицы, определённые в базе данных ClickHouse, в схему PostgreSQL как внешние таблицы:
Используйте LIMIT TO, чтобы импортировать только указанные таблицы:
Используйте EXCEPT, чтобы исключить таблицы:
pg_clickhouse получит список всех table в указанной базе данных (“demo” в примерах выше), получит определения столбцов для каждой из них и выполнит команды CREATE FOREIGN TABLE, чтобы создать внешние таблицы. Столбцы будут определены с использованием поддерживаемых типов данных и, если это удастся определить, параметров, поддерживаемых CREATE FOREIGN TABLE. Некоторые моменты, которые следует учитывать:
  • Импортированные столбцы сохраняют модификатор типа 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, приводят к ошибке.
Сохранение регистра импортированных идентификаторовIMPORT FOREIGN SCHEMA применяет quote_identifier() к именам table и столбцов, которые импортирует, из-за чего идентификаторы с символами в верхнем регистре или пробелами заключаются в двойные кавычки. Поэтому такие имена table и столбцов в запросах PostgreSQL также должны быть заключены в двойные кавычки. Имена, состоящие только из строчных букв и не содержащие пробелов, заключать в кавычки не нужно.Например, для такой таблицы ClickHouse:
IMPORT FOREIGN SCHEMA создаёт такую внешнюю таблицу:
Поэтому в запросах нужно правильно использовать кавычки, например:
Чтобы создавать объекты с другими именами или именами только в нижнем регистре (и, следовательно, регистронезависимыми), используйте CREATE FOREIGN TABLE.

CREATE FOREIGN TABLE

Используйте CREATE FOREIGN TABLE для создания внешней таблицы, позволяющей запрашивать данные из базы данных ClickHouse:
Поддерживаются следующие параметры таблицы:
  • database: Имя удалённой базы данных. По умолчанию используется база данных, заданная для внешнего сервера.
  • table_name: Имя удалённой таблицы. По умолчанию используется имя, указанное для внешней таблицы.
  • engine: [движок таблицы], используемый таблицей ClickHouse. Для CollapsingMergeTree() и AggregatingMergeTree() pg_clickhouse автоматически применяет параметры к функциональным выражениям, выполняемым для таблицы.
Используйте тип данных, соответствующий удалённому типу данных 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, чтобы изменить описание внешней таблицы:
Поддерживаемые параметры таблицы и столбца совпадают с параметрами для CREATE FOREIGN TABLE.

DROP FOREIGN TABLE

Чтобы удалить внешнюю таблицу, используйте DROP FOREIGN TABLE:
Эта команда завершится ошибкой, если существуют объекты, зависящие от внешней таблицы. Чтобы удалить и их, используйте предложение CASCADE:

Справочник по DML SQL

Приведённые ниже SQL-выражения DML могут использовать pg_clickhouse. В примерах ниже используются следующие таблицы ClickHouse:

EXPLAIN

Команда EXPLAIN работает как ожидается, но параметр VERBOSE приводит к выводу запроса ClickHouse “Remote SQL”:
Этот запрос передаётся в ClickHouse через узел плана “Foreign Scan” как удалённый SQL.

SELECT

Используйте оператор SELECT для выполнения запросов к таблицам pg_clickhouse, как и к любым другим таблицам:
pg_clickhouse старается по возможности максимально переносить выполнение запроса в ClickHouse, включая агрегатные функции. Используйте EXPLAIN, чтобы определить степень использования pushdown. Например, для приведённого выше запроса всё выполнение переносится в ClickHouse
pg_clickhouse также выполняет pushdown JOIN для таблиц, находящихся на одном и том же удалённом сервере:
JOIN с локальной таблицей без тщательной настройки приведёт к менее эффективным запросам. В этом примере мы создаём локальную копию таблицы nodes и выполняем JOIN с ней вместо удалённой таблицы:
В этом случае мы можем перенести большую часть агрегации в ClickHouse, выполнив группировку по node_id вместо локального столбца, а затем выполнить JOIN с таблицей lookup:
Узел “Foreign Scan” теперь выполняет агрегацию по node_id, сокращая число строк, которые нужно вернуть в Postgres, с 1000 (то есть всех) до всего 8 — по одной на каждый узел.

Партиционированные таблицы

[Партиционированная таблица] PostgreSQL может сочетать локальные партиции с внешними партициями, размещёнными в ClickHouse. Распространённая структура предполагает перенос старых данных в ClickHouse, тогда как новые данные остаются в PostgreSQL:
Пример переноса данных из локальных партиций во внешние см. в файле offload-partition.sql. Для агрегирования данных по локальным и внешним партициям требуется [пораздельная агрегация партиций], которая в 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 …) проталкивается вместе с этими агрегатными функциями.

Когда используется локальная обработка

Агрегатные функции, состояние перехода которых имеет непрозрачный тип PostgreSQL internal, не имеют переносимого представления, поэтому внешняя партиция вместо этого загружает свои строки и выполняет агрегацию локально. Это относится ко всем агрегатам для numeric, а также к avg(bigint) и avg(interval). Агрегаты DISTINCT, упорядоченных множеств и вариативные агрегаты также используют локальную обработку.

PREPARE, EXECUTE, DEALLOCATE

Начиная с версии v0.1.2, pg_clickhouse поддерживает параметризованные запросы, которые в основном создаются с помощью команды PREPARE:
Используйте EXECUTE как обычно для выполнения подготовленного оператора:
pg_clickhouse, как обычно, проталкивает агрегации, что видно в подробном выводе EXPLAIN:
Обратите внимание, что были отправлены полные значения дат, а не плейсхолдеры параметров. Так происходит для первых пяти запросов, как описано в [заметках о PREPARE]. При шестом выполнении отправляются ClickHouse [параметры запроса] в формате {param:type}:
Используйте DEALLOCATE, чтобы освободить подготовленный оператор:

INSERT

Используйте команду INSERT, чтобы вставить значения в удалённую таблицу ClickHouse:

COPY

Используйте команду COPY, чтобы выполнить вставку батча строк в удалённую таблицу ClickHouse:
⚠️ Ограничения Batch API В pg_clickhouse пока не реализована поддержка Batch API вставки PostgreSQL FDW. Поэтому COPY сейчас использует операторы INSERT для вставки записей. Это будет исправлено в одном из будущих релизов.

LOAD

С помощью LOAD загрузите разделяемую библиотеку pg_clickhouse:
Обычно использовать LOAD не требуется, так как Postgres автоматически загрузит pg_clickhouse при первом использовании любой из его возможностей (функций, внешних таблиц и т. д.). Единственный случай, когда LOAD pg_clickhouse может быть полезен, — это SET параметров pg_clickhouse перед выполнением запросов, которые от них зависят.

SET

Используйте SET, чтобы установить пользовательские параметры конфигурации pg_clickhouse.

pg_clickhouse.session_settings

Параметр pg_clickhouse.session_settings задаёт [настройки ClickHouse], которые будут применяться к последующим запросам. Пример:
По умолчанию:
Установите это значение в пустую строку, чтобы использовать настройки сервера ClickHouse — однако учтите, что корректность pushdown зависит от некоторых значений по умолчанию: join_use_nulls для внешних JOIN и transform_null_in для семейства IN (см. IN и семантика NULL).
Синтаксис представляет собой список пар ключ/значение, разделённых запятыми и отделённых друг от друга одним или несколькими пробелами. Ключи должны соответствовать [настройкам ClickHouse]. Экранируйте пробелы, запятые и символы обратной косой черты в значениях с помощью обратной косой черты:
Или используйте значения в одинарных кавычках, чтобы не экранировать пробелы и запятые; также можно использовать dollar quoting, чтобы не нужно было заключать их в двойные кавычки:
Если для вас важна читаемость и нужно задать много параметров, используйте несколько строк, например:
Некоторые настройки будут игнорироваться в случаях, когда они могли бы помешать работе самого pg_clickhouse. К ним относятся:
  • date_time_output_format: HTTP-драйвер требует, чтобы значение было “iso”
  • format_tsv_null_representation: HTTP-драйвер требует значение по умолчанию
  • output_format_tsv_crlf_end_of_line HTTP-драйвер требует значение по умолчанию
В остальных случаях pg_clickhouse не проверяет настройки, а передаёт их в ClickHouse для каждого запроса. Таким образом, он поддерживает все настройки каждой версии ClickHouse. Обратите внимание: pg_clickhouse должен быть загружен до установки 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:
Полезно, если нужно воспользоваться обновлениями без перезапуска сервера: просто подключитесь заново. Также это можно задать для конкретных пользователей или ролей через ALTER ROLE.

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 выведет:
Внешняя таблица, использующая столбцы [TEXT], как правило, не может прочитать эти значения как текст, поскольку pg_clickhouse проверяет байты ClickHouse на соответствие кодировке базы данных:
Вывод:
Дайджест содержит произвольные байты, которые редко образуют допустимый текст. Кроме того, PostgreSQL резервирует нулевой байт, поэтому столбец [TEXT] никогда не прочитает строку ClickHouse, если она его содержит. Попытка вставить бинарные значения в столбцы [TEXT] завершится успешно и будет работать как ожидается:
Значения в текстовых столбцах будут корректными:
Но если читать их как BYTEA, этого не произойдет:
Столбец FixedString(N) дополняет короткие значения нулевыми байтами. Текстовый столбец отбрасывает эти завершающие нулевые байты, тогда как столбец BYTEA сохраняет каждый байт.
Как правило, столбцы [TEXT] следует использовать только для закодированных строк, а столбцы BYTEA — только для двоичных данных; никогда не чередуйте их.

Составные типы

Array

Тип [Array] в ClickHouse напрямую сопоставляется с массивами PostgreSQL с эквивалентной семантикой. Основное отличие в том, что в многомерных массивах Postgres вложенные выражения массивов должны иметь одинаковую размерность. Попытка прочитать массив ClickHouse с разной размерностью, например [[1], [2,3]], приводит к ошибке. Доступ к элементам массива по индексу проталкивается в удалённую систему там, где это возможно, включая доступ по индексу в многомерных массивах. Примеры:
Срезы массивов также проталкиваются с помощью функции [arraySlice], однако доступ к многомерным срезам пока не поддерживается:

Map

В PostgreSQL нет типа, соответствующего типу ClickHouse [Map]. Поэтому pg_clickhouse отображает столбцы [Map] в text[][], где каждая пара ключ-значение представлена отдельным массивом. Именно это отображение использует IMPORT FOREIGN SCHEMA. Значения Map также можно вставлять с помощью INSERT в виде массивов. Пример:
Каждый вложенный массив должен содержать ровно два текстовых значения. Значения, несовместимые с соответствующими типами ключа или значения в ClickHouse, вызывают ошибку.
Для вставки 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 с помощью стандартных возможностей массивов, включая синтаксис обращения к элементам по индексу:
Столбец [Nested], созданный с flatten_nested=0, отображается в массив, в котором каждой вложенной строке соответствует один элемент. Каждый элемент массива содержит значения этой строки:
Теперь итоговая схема выглядит так:
Представляйте вложенные записи в виде двумерного массива, текстовые значения в котором отформатированы в соответствии с типами, определёнными в столбце ClickHouse. Для c2 Nested(id Int64, name String) из этого примера это будет выглядеть так:
Однако pushdown столбцов text[][] в типы Nested завершается ошибкой:
Это связано с тем, что pg_clickhouse не может отличить текстовый массив, сопоставленный столбцу типа Array в ClickHouse, от массива, сопоставленного столбцу Nested, и поэтому не может переписать его с использованием синтаксиса Nested в ClickHouse. Однако эти элементы можно сопоставить и с массивом соответствующего составного типа (подробнее см. Ручное сопоставление типов). В этом случае pushdown работает при условии, что имена полей составного типа совпадают с именами полей Nested:

Ручное сопоставление типов

IMPORT FOREIGN SCHEMA использует универсальные типы PostgreSQL. Например, возьмём таблицу ClickHouse со столбцами типов [Enum], [Tuple], Map и неуплощённого [Nested] (flatten_nested = 0), такую как:
Чтобы сохранить структуру или ограничить допустимые значения, определите в PostgreSQL составные типы или типы-перечисления (enum) и создайте внешнюю таблицу вручную:
Всегда задавайте метки enum и имена полей составных типов такими же, как метки enum в ClickHouse и имена полей Nested или Tuple, чтобы при pushdown использовались правильные имена.
Порядок и типы полей составных типов должны совпадать с объявлениями в ClickHouse. Ключи и значения [Map] становятся соответственно первым и вторым полями (в данном случае key и value). Nested и Map превращаются в массивы составных значений, а Tuple — в одно составное значение:
Разумеется, имена полей составного типа тоже можно использовать — как в списке SELECT:
А также для типов [Nested] в предложении WHERE — при условии, что имена полей совпадают:
INSERT с использованием таких составных типов пока не поддерживается.

Справочник по Function и операторам

Функции

Эти функции служат интерфейсом для выполнения запросов к базе данных ClickHouse.

clickhouse_server_version

Возвращает версию сервера ClickHouse в формате major.minor.patch для указанного стороннего сервера, при необходимости подключаясь с использованием параметров сервера и пользовательского сопоставления текущего пользователя:
Получает версию из рукопожатия соединения по нативному протоколу или по HTTP с помощью единственного запроса SELECT version() и кэширует её на весь срок жизни соединения.

clickhouse_query

Выполняет запрос к уже настроенному стороннему серверу и возвращает его строки в виде отношения, сопоставляя каждый столбец результата ClickHouse с типом PostgreSQL, указанным в списке определений столбцов. Повторно использует driver сервера, учётные данные, базу данных и кэш подключений. Первый аргумент — имя сервера, созданного с помощью CREATE SERVER. Требуется список определений столбцов (AS name(col type, ...)): PostgreSQL необходимо знать структуру результата до получения строк, и она должна соответствовать столбцам, которые возвращает запрос. Значения преобразуются из ClickHouse в объявленные типы так же, как для столбца внешней таблицы. Операторам, не возвращающим результаты, например DDL, нечего объявлять; вместо этого выполняйте их с помощью clickhouse_perform. По умолчанию ни одна роль не имеет права EXECUTE; предоставьте его роли, чтобы разрешить ей использовать функцию.

clickhouse_perform

Выполняет оператор на предварительно настроенном стороннем сервере и отбрасывает любой результат. Используйте его для операторов, не возвращающих строк, например DDL, когда clickhouse_query не имеет формы результата, которую можно объявить. Он разрешает сервер так же, как clickhouse_query, повторно используя его driver, учётные данные, базу данных и кэш подключений. Как процедуру его следует вызывать с помощью CALL, а не SELECT; он не возвращает строк. По умолчанию ни у одной роли нет права EXECUTE; предоставьте его роли с помощью GRANT, чтобы она могла использовать процедуру.

Функции с pushdown

pg_clickhouse выполняет pushdown для части встроенных функций PostgreSQL, используемых в условных выражениях (в секциях HAVING и WHERE). Для них используются следующие эквиваленты в ClickHouse:

Операторы 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:

intarray

Одна функция [intarray] выполняется в ClickHouse:

fuzzystrmatch

В ClickHouse проталкиваются две функции [fuzzystrmatch]:

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.

Пользовательские агрегаты

Эти пользовательские агрегатные функции, созданные в pg_clickhouse, обеспечивают pushdown внешних запросов для некоторых агрегатных функций ClickHouse, не имеющих эквивалентов в PostgreSQL. Если какую-либо из этих функций невозможно передать через pushdown, будет вызвано исключение.

Pushdown для агрегатных функций ordered set

Эти [агрегатные функции ordered set] сопоставляются с [параметрическими агрегатными функциями] ClickHouse путём передачи их непосредственного аргумента в качестве параметра, а выражений ORDER BY — в качестве аргументов. Например, следующий запрос PostgreSQL:
Преобразуется в следующий запрос к ClickHouse:
Обратите внимание, что нестандартные суффиксы ORDER BY — DESC и NULLS FIRST — не поддерживаются и вызовут ошибку.

Пользовательская агрегатная функция ordered set

Эти пользовательские [агрегатные функции ordered set], созданные pg_clickhouse, обеспечивают pushdown внешних запросов для некоторых [параметрических агрегатных функций] ClickHouse. Если какую-либо из этих функций не удаётся выполнить с pushdown, будет вызвано исключение.

Пользовательские агрегатные функции ordered set

Эти пользовательские [агрегатные функции ordered set], созданные pg_clickhouse, поддерживают pushdown внешних запросов для отдельных параметрических [агрегатных функций] ClickHouse. Если любую из этих функций нельзя выполнить с pushdown, будет вызвано исключение.

Оконные функции с pushdown

Эти [оконные функции] PostgreSQL проталкиваются в ClickHouse с секциями OVER (PARTITION BY ... ORDER BY ...), включая спецификации рамки окна, где это применимо. При pushdown функции ранжирования (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 возвращать пустой массив и тем самым сравнивать возвращаемые значения единообразно. Например:
Чтобы полностью избежать неоднозначности, рассмотрите возможность установки pg_clickhouse.pushdown_regex, чтобы предотвратить передачу регулярных выражений Postgres через pushdown в ClickHouse, и используйте [re2 extension], для которого pg_clickhouse поддерживает прямой pushdown совместимых с ClickHouse регулярных выражений [RE2].

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&#95;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”