SELECT and INSERT queries on data stored on a remote PostgreSQL server.
Currently, only PostgreSQL versions 12 and up are supported for the table engine.
Creating a table
- Column names should be the same as in the original PostgreSQL table, but you can use just some of these columns and in any order.
- Column types may differ from those in the original PostgreSQL table. ClickHouse tries to cast values to the ClickHouse data types.
- The external_table_functions_use_nulls setting defines how to handle Nullable columns. Default value: 1. If 0, the table function does not make Nullable columns and inserts default values instead of nulls. This is also applicable for NULL values inside arrays.
host:port— PostgreSQL server address.database— Remote database name.table— Remote table name, or a query passed to PostgreSQL as is (see Passing a query instead of a table name).user— PostgreSQL user.password— User password.schema— Non-default table schema. Optional.on_conflict— Conflict resolution strategy. Example:ON CONFLICT DO NOTHING. Optional. Note: adding this option will make insertion less efficient.
Implementation details
SELECT queries on PostgreSQL side run as COPY (SELECT ...) TO STDOUT inside read-only PostgreSQL transaction with commit after each SELECT query.
Simple WHERE clauses such as =, !=, >, >=, <, <=, and IN are executed on the PostgreSQL server.
All joins, aggregations, sorting, IN [ array ] conditions and the LIMIT sampling constraint are executed in ClickHouse only after the query to PostgreSQL finishes.
Passing a query instead of a table name
Instead of a table name, thetable argument can be a SELECT query that is passed to PostgreSQL as is. The structure of the table is inferred from the query result. The query can be written either as a subquery, or wrapped into the query function:
INSERT into it is not allowed. The same syntax is supported by the postgresql table function.
The subquery form
(SELECT ...) is parsed by ClickHouse and re-serialized in the PostgreSQL dialect (PostgreSQL identifier quoting and string-literal escaping) before being sent to the server. It must therefore be valid ClickHouse SQL. To pass PostgreSQL-specific syntax that ClickHouse does not parse, use the query('...') form, whose text is sent to PostgreSQL verbatim.Any outer WHERE, LIMIT, aggregation, etc. of the surrounding ClickHouse query is not pushed down into the passed query — it is applied in ClickHouse after the full query result is fetched. To restrict the data read from PostgreSQL, put the filter inside the passed query. With external_table_strict_query = 1 an outer filter that cannot be pushed down is rejected with an exception instead of being applied locally.INSERT queries on PostgreSQL side run as COPY "table_name" (field1, field2, ... fieldN) FROM STDIN inside PostgreSQL transaction with auto-commit after each INSERT statement.
PostgreSQL Array types are converted into ClickHouse arrays.
Be careful - in PostgreSQL an array data, created like a
type_name[], may contain multi-dimensional arrays of different dimensions in different table rows in same column. But in ClickHouse it is only allowed to have multidimensional arrays of the same count of dimensions in all table rows in same column.|. For example:
0.
In the example below replica example01-1 has the highest priority: