{"article":{"slug":"introducing-chdb-postgres-extension-high-performance-imports-from-cloud-storage","title":"Introducing chdb Postgres extension: High-performance imports from cloud storage","subtitle":null,"summary":"ClickHouse announces the chdb Postgres extension: fast imports and exports across cloud storage and formats, powered by the embedded ClickHouse engine and usable via COPY-style workflows.","content_type":"blog_post","language":"en","canonical_url":"https://clickhouse.com/blog/introducing-chdb-postgres","author":{"name":"David Wheeler","url":"https://clickhouse.com/blog","person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"ClickHouse","url":"https://clickhouse.com/","listing_slug":null,"listing":null},"topics":[{"name":"Databases","slug":"databases","url":"https://listedarticles.com/topics/databases"},{"name":"PostgreSQL","slug":"postgresql","url":"https://listedarticles.com/topics/postgresql"},{"name":"Data Engineering","slug":"data-engineering","url":"https://listedarticles.com/topics/data-engineering"},{"name":"Performance","slug":"performance","url":"https://listedarticles.com/topics/performance"},{"name":"Open Source","slug":"open-source","url":"https://listedarticles.com/topics/open-source"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":1599,"reading_minutes":7,"published_at":"2026-09-08T12:00:00.000Z","added_at":"2026-09-19T18:16:03.665Z","updated_at":"2026-09-19T18:16:03.665Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":false},"profile_url":"https://listedarticles.com/articles/introducing-chdb-postgres-extension-high-performance-imports-from-cloud-storage","markdown_url":"https://listedarticles.com/articles/introducing-chdb-postgres-extension-high-performance-imports-from-cloud-storage.md","example":false,"citation":"David Wheeler, ClickHouse. \"Introducing chdb Postgres extension: High-performance imports from cloud storage.\" 8 Sept 2026. https://clickhouse.com/blog/introducing-chdb-postgres (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://clickhouse.com/blog/introducing-chdb-postgres"},"body_markdown":"We're happy to announce a new Postgres extension: [chdb](https://pgxn.org/dist/chdb/). This extension expands Postgres import and export features via the [chDB library](https://clickhouse.com/docs/chdb), an in-process [ClickHouse](https://github.com/ClickHouse/ClickHouse) engine, providing efficient, flexible conversion to and from a wide array of [data formats](https://clickhouse.com/docs/reference/formats/index) living on your favorite cloud storage systems.\n\n## Benchmark #\n\nAnd _boy howdy_ do we mean _efficient_! We compared [chdb](https://pgxn.org/dist/chdb/)'s performance importing the [NYC Taxi dataset](https://clickhouse.com/docs/get-started/quickstarts/tutorial) (1m rows, wide table) in a number of data formats to three other Postgres extensions, all reading from a regionally-colocated [AWS S3](https://aws.amazon.com/s3/) bucket. To the chart!\n\n> In order to minimize differences and to optimize for measurement of extension performance rather than infrastructure, the [chdb](https://pgxn.org/dist/chdb/), [pg_lake](https://github.com/Snowflake-Labs/pg_lake), and [pg_duckdb](https://github.com/duckdb/pg_duckdb) benchmarks ran on `r8id.xlarge` [ClickHouse Managed Postgres](https://clickhouse.com/cloud/postgres) services with 4 vCPUs and 32 GB RAM; the [aws_s3](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.S3Import.html) benchmark ran on a `db.r8g.xlarge` [AWS RDS](https://aws.amazon.com/rds/postgresql/) host, also with 4 vCPUs and 32 GB RAM. Results average three runs for each import. See the [benchmark source code](https://github.com/ClickHouse/pg_chdb/blob/main/dev/benchmark/) for details.\n\nOf the four extensions, [chdb](https://pgxn.org/dist/chdb/) exhibits the most consistent performance. [pg_duckdb](https://github.com/duckdb/pg_duckdb) and [pg_lake](https://github.com/Snowflake-Labs/pg_lake), both backed by [DuckDB](https://duckdb.org), take around 2-3x as long to import data from CSV, JSON, and Parquet. Only [aws_s3](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.S3Import.html) approaches [chdb](https://pgxn.org/dist/chdb/)'s performance, but it supports a much more limited array of data formats.\n\n## Data formats #\n\nDid we mention data formats? The [chdb](https://pgxn.org/dist/chdb/) extension can read and write a slew of data formats --- all those that [ClickHouse itself supports](https://clickhouse.com/docs/reference/formats/index). This table summarizes the supported data formats and compression algorithms of the extensions we compared; note that this [chdb](https://pgxn.org/dist/chdb/) list of formats is but a subset of the [formats it supports](https://clickhouse.com/docs/reference/formats/index):\n\nExtension| Compression| Data Formats  \n---|---|---  \naws_s3| none| Text (TSV), CSV, Postgres Binary  \npg_lake| gzip, zstd, snappy (Parquet only)| CSV, JSON, Parquet  \npg_duckdb| gzip, zstd, snappy (Parquet only)| CSV, JSON, Parquet  \nchdb| gzip, zstd, lz4, bz2, snappy, brotli| TSV, CSV, JSON, BSON, Prometheus, Protobuf, Avro, Parquet, Arrow, XML, CapnProto, Markdown, MsgPack, ORC, and [more](https://clickhouse.com/docs/reference/formats/index)!  \n  \nAs [ClickHouse](https://github.com/ClickHouse/ClickHouse) and the [chDB library](https://clickhouse.com/docs/chdb) add more, the [chdb](https://pgxn.org/dist/chdb/) extension will get them for free!\n\nWe benchmarked [chdb](https://pgxn.org/dist/chdb/) performance loading the [NYC Taxi dataset](https://clickhouse.com/docs/get-started/quickstarts/tutorial) for a number of these formats, where it demonstrated quite consistent performance:\n\nWe used the [JSONCompact](https://clickhouse.com/docs/reference/formats/JSON/JSONCompact) format for compatibility with the other extensions. Other JSON formats, such as [JSONCompactEachRow](https://clickhouse.com/docs/reference/formats/JSON/JSONCompactEachRow), will more closely approximate the performance of the other formats.\n\n## Usage #\n\nThe [chdb](https://pgxn.org/dist/chdb/) package ships with two extensions: a [CREATE EXTENSION](https://www.postgresql.org/docs/current/sql-createextension.html) extension named chdb and a [hook module](https://wiki.postgresql.org/wiki/PostgresServerExtensionPoints#Hooks) named chdb_hook.\n\n### chdb extension #\n\nThe chdb extension ([docs](https://pgxn.org/dist/chdb/doc/chdb.html)) provides the `chdb_query()` function, which executes a single chDB query. For example, this query:\n    \n    \n    1SELECT * FROM chdb_query($$\n    2  SELECT * FROM s3('s3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv');\n    3$$) AS (id int, months int, days int);\n\nCopy command\n\nOutputs:\n    \n    \n    1id | months | days\n    2----+--------+------\n    3  1 |      2 |    3\n    4  3 |      2 |    1\n    5  4 |      5 |    6\n    6(3 rows)\n\nCopy command\n\n### chdb_hook module #\n\nThe `chdb_hook` module ([docs](https://pgxn.org/dist/chdb/doc/chdb_hook.html)) hooks into the [COPY](https://www.postgresql.org/docs/current/sql-copy.html) command to copy data to or from an [AWS S3](https://aws.amazon.com/s3/), [Google Cloud Storage](https://cloud.google.com/storage), [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs/), file, or http URL. This example loads records from a CSV file on S3:\n    \n    \n    1CREATE TABLE times (\n    2    id     INT NOT NULL,\n    3    months INT NOT NULL,\n    4    days   INT NOT NULL\n    5);\n    6\n    7LOAD 'chdb_hook';\n    8COPY times FROM 's3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv';\n\nCopy command\n\nAfter which the `times` table contains the records from the file:\n    \n    \n    1# SELECT * FROM times;\n    2 id | months | days\n    3----+--------+------\n    4  1 |      2 |    3\n    5  3 |      2 |    1\n    6  4 |      5 |    6\n    7(3 rows)\n\nCopy command\n\nA [CREATE TABLE](https://www.postgresql.org/docs/current/sql-createtable.html) command may also derive its columns, and load its rows, from such a URL. Try this one (all the URLs in this piece point to legit data files):\n    \n    \n    1CREATE TABLE reviews () WITH (\n    2    copy_from = 's3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet'\n    3);\n\nCopy command\n\nThe resulting, fully-loaded table has this structure:\n\nColumn| Type  \n---|---  \nreview_date| integer  \nmarketplace| text  \ncustomer_id| numeric(20,0)  \nreview_id| text  \nproduct_id| text  \nproduct_parent| numeric(20,0)  \nproduct_title| text  \nproduct_category| text  \nstar_rating| smallint  \nhelpful_votes| bigint  \ntotal_votes| bigint  \nvine| boolean  \nverified_purchase| boolean  \nreview_headline| text  \nreview_body| text  \n  \n## Data types #\n\nLike [pg_clickhouse](https://clickhouse.com/docs/products/managed-postgres/extensions/pg_clickhouse/), [chdb](https://pgxn.org/dist/chdb/) relies on the [pg-clickhouse-c](https://github.com/ClickHouse/pg-clickhouse-c/) headers-only library to convert values from ClickHouse to Postgres, including its [type mapping](https://github.com/ClickHouse/pg-clickhouse-c/#type-mapping), as in the `CREATE TABLE` example above. The current release maps nearly all of the ClickHouse types to Postgres types and vice versa. These mappings work most of the time; when they don't, use the `structure` option to tell [chdb](https://pgxn.org/dist/chdb/) what type to use.\n\nFor example, [pg-clickhouse-c](https://github.com/ClickHouse/pg-clickhouse-c/) maps a Postgres JSON value to ClickHouse String, because [ClickHouse JSON](https://clickhouse.com/docs/reference/data-types/newjson) currently recognizes only JSON _objects_ , while Postgres JSON supports objects, arrays, and JSON scalar values. But perhaps you're confident your JSON columns contain only objects, thanks to a check constraint:\n    \n    \n    1CREATE TABLE projects (\n    2    name   TEXT PRIMARY KEY,\n    3    meta   JSON NOT NULL CHECK (json_typeof(meta) = 'object')\n    4);\n    5\n    6INSERT INTO projects\n    7VALUES ( 'chdb',   '{\"status\": \"release\"}' ),\n    8       ( 'walrus', '{\"status\": \"revise\"}'  );\n\nCopy command\n\nTo benefit from the increased flexibility and storage for object-aware storage formats such as [Parquet JSON](https://parquet.apache.org/docs/file-format/types/logicaltypes/#json), use the `structure` option to map it to [ClickHouse JSON](https://clickhouse.com/docs/reference/data-types/newjson):\n    \n    \n    1COPY projects to 'file:///tmp/projects.parquet' (\n    2    structure 'name String, meta JSON'\n    3);\n\nCopy command\n\n## Cloud storage URLs #\n\nThe [chdb_hook](https://pgxn.org/dist/chdb/doc/chdb_hook.html) extension reads and writes to all your favorite storage platforms. It determines the appropriate protocol from the URL scheme.\n\nSchemes| Target  \n---|---  \n`file`| Absolute path on the Postgres server  \n`http`, `https`| HTTP URL  \n`s3`| [AWS S3](https://aws.amazon.com/s3/)  \n`gs`, `gcs`, `oss`| [Google Cloud Storage](https://cloud.google.com/storage)  \n`az`, `azure`, `abfss`, `abfs`| [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs/) or [Azure ABFS](https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction-abfs-uri)  \n`hdfs`| [Hadoop Distributed File System](https://en.wikipedia.org/wiki/Apache_Hadoop#Overview)  \n  \nURLs may also use a number of [wildcards](https://pgxn.org/dist/chdb/doc/chdb_hook.html#Path.Wildcards) to concurrently fetch multiple files. Revisiting the `CREATE TABLE` example above, this command finds and imports six files from S3:\n    \n    \n    1CREATE TABLE times () WITH (\n    2    copy_from = 's3://datasets-documentation/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv'\n    3);\n\nCopy command\n\nAfter which the `times` table contains the records from each file it loaded:\n    \n    \n    1SELECT * FROM times;\n    2 c1 | c2 | c3 \n    3----+----+----\n    4  1 |  2 |  3\n    5  3 |  2 |  1\n    6  4 |  5 |  6\n    7  1 |  2 |  3\n    8  3 |  2 |  1\n    9  4 |  5 |  6\n    10  1 |  2 |  3\n    11  3 |  2 |  1\n    12  4 |  5 |  6\n    13  1 |  2 |  3\n    14  3 |  2 |  1\n    15  4 |  5 |  6\n    16  1 |  2 |  3\n    17  3 |  2 |  1\n    18  4 |  5 |  6\n    19  1 |  2 |  3\n    20  3 |  2 |  1\n    21  4 |  5 |  6\n    22 (18 rows)\n\nCopy command\n\n## Architecture #\n\nSupport for such a vast array of data formats and cloud platforms demands a panoply of dependencies. We avoid managing those dependencies by delegating the problem to the [chDB library](https://clickhouse.com/docs/chdb). But loading that library into a Postgres backend would be excessive, especially for typically occasional or periodic tasks such as loading from a data source once a day.\n\nData loading extensions thus take a variety of approaches to managing the size and complexity of such a library by a variety of means:\n\n  * [aws_s3](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.S3Import.html) simply downloads files to the local file system and passes control to [COPY](https://www.postgresql.org/docs/current/sql-copy.html); hence its limitation to [AWS S3](https://aws.amazon.com/s3/) sources and the formats that Postgres [COPY](https://www.postgresql.org/docs/current/sql-copy.html) supports\n  * [pg_duckdb](https://github.com/duckdb/pg_duckdb) embeds the [DuckDB](https://duckdb.org) engine in the Postgres backend, overkill for occasional [COPY](https://www.postgresql.org/docs/current/sql-copy.html) needs\n  * [pg_lake](https://github.com/Snowflake-Labs/pg_lake) runs a separate [DuckDB](https://duckdb.org)-powered service and communicates with it via the [libpq protocol](https://www.postgresql.org/docs/current/libpq.html), which permanently consumes resources on the Postgres host\n\nThe [chdb extension](https://pgxn.org/dist/chdb/) adopts its own distinctive architecture: It embeds the [chDB library](https://clickhouse.com/docs/chdb) into a separate helper application. Neither the extension nor [chdb_hook](https://pgxn.org/dist/chdb/doc/chdb_hook.html) link chDB. Instead, they start the helper app on demand and communicate with it via an efficient, in-memory channel: file descriptors (`STDIN`, `STDOUT`, and `STDERR`, plus another for configuration information).\n\nThis design prevents the [chDB library](https://clickhouse.com/docs/chdb) from consuming any more resources than necessary to carry out a single command. It also isolates the PostgreSQL cluster itself from [out of memory](https://en.wikipedia.org/wiki/Out_of_memory) issues that using shared memory with a [background worker](https://www.postgresql.org/docs/current/bgworker.html) would suffer.\n\nWhen the helper app finishes executing a command and has passed all its results to the backend (in [ClickHouse Native](https://clickhouse.com/docs/reference/formats/Native) format, straight from the source), it simply cleans up and exits, leaving the server resources to the service that most matters: PostgreSQL.\n    \n    \n    1+-------------+\n    2                  |   helper    |\n    3+----------+      |    app      |      +------+\n    4| Postgres |      | +---------+ |      | chDB |\n    5| Backend  |<---->| |  chDB   | |<---->| Data |\n    6+----------+      | | Library | |      +------+\n    7                  | +---------+ |\n    8                  +-------------+\n\nCopy command\n\n## What's next? #\n\nWe plan to continue making [chdb](https://pgxn.org/dist/chdb/) better. Potential roadmap items include:\n\n  * Complete type mapping. We're gradually filling in the gap between Postgres and ClickHouse data types, to the benefit of both [chdb](https://pgxn.org/dist/chdb/) and [pg_clickhouse](https://clickhouse.com/docs/products/managed-postgres/extensions/pg_clickhouse/).\n  * Access control to object storage via credential chain. Currently credentials required to read and write object stores must be passed explicitly in each [chdb](https://pgxn.org/dist/chdb/) call. We'd like to allow transparent, server-configured credentialing to work as well.\n  * Support for `COPY (query) TO`\n  * Support for a `WHERE` condition on [COPY](https://www.postgresql.org/docs/current/sql-copy.html)\n  * Support for all of the existing [COPY](https://www.postgresql.org/docs/current/sql-copy.html) options\n  * Support for the [Iceberg](https://iceberg.apache.org) format\n  * Query files directly from storage\n\n## Give it a try #\n\nFind the [chdb extension](https://pgxn.org/dist/chdb/) in all the usual places, including [GitHub](https://github.com/ClickHouse/pg_chdb) and [PGXN](https://pgxn.org/dist/chdb/). We also provide it as part of the broader [pg_clickhouse](https://clickhouse.com/docs/products/managed-postgres/extensions/pg_clickhouse/) package on [ClickHouse Managed Postgres](https://clickhouse.com/cloud/postgres); ask your support contact to add `chdb_hook` to your default configuration, or just connect to a superuser account via `psql` or your favorite client, run `CREATE EXTENSION chdb;` or `LOAD 'chdb_hook';` and get started!\n\n### Get started with ClickHouse Managed Postgres today\n\nInterested in seeing how ClickHouse Managed Postgres works on your data? Get started with ClickHouse Cloud in minutes and receive $300 in free credits.\n\n[Sign up](https://console.clickhouse.cloud/signUp?intent=pg&loc=blog-cta-1837-get-started-with-clickhouse-managed-postgres-today-sign-up&utm_blogctaid=1837)","body_html":"<p>We&#39;re happy to announce a new Postgres extension: <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a>. This extension expands Postgres import and export features via the <a href=\"https://clickhouse.com/docs/chdb\" rel=\"nofollow ugc noopener\">chDB library</a>, an in-process <a href=\"https://github.com/ClickHouse/ClickHouse\" rel=\"nofollow ugc noopener\">ClickHouse</a> engine, providing efficient, flexible conversion to and from a wide array of <a href=\"https://clickhouse.com/docs/reference/formats/index\" rel=\"nofollow ugc noopener\">data formats</a> living on your favorite cloud storage systems.</p>\n<h2 id=\"benchmark\">Benchmark</h2>\n<p>And <em>boy howdy</em> do we mean <em>efficient</em>! We compared <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a>&#39;s performance importing the <a href=\"https://clickhouse.com/docs/get-started/quickstarts/tutorial\" rel=\"nofollow ugc noopener\">NYC Taxi dataset</a> (1m rows, wide table) in a number of data formats to three other Postgres extensions, all reading from a regionally-colocated <a href=\"https://aws.amazon.com/s3/\" rel=\"nofollow ugc noopener\">AWS S3</a> bucket. To the chart!</p>\n<blockquote><p>In order to minimize differences and to optimize for measurement of extension performance rather than infrastructure, the <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a>, <a href=\"https://github.com/Snowflake-Labs/pg_lake\" rel=\"nofollow ugc noopener\">pg_lake</a>, and <a href=\"https://github.com/duckdb/pg_duckdb\" rel=\"nofollow ugc noopener\">pg_duckdb</a> benchmarks ran on <code>r8id.xlarge</code> <a href=\"https://clickhouse.com/cloud/postgres\" rel=\"nofollow ugc noopener\">ClickHouse Managed Postgres</a> services with 4 vCPUs and 32 GB RAM; the <a href=\"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.S3Import.html\" rel=\"nofollow ugc noopener\">aws_s3</a> benchmark ran on a <code>db.r8g.xlarge</code> <a href=\"https://aws.amazon.com/rds/postgresql/\" rel=\"nofollow ugc noopener\">AWS RDS</a> host, also with 4 vCPUs and 32 GB RAM. Results average three runs for each import. See the <a href=\"https://github.com/ClickHouse/pg_chdb/blob/main/dev/benchmark/\" rel=\"nofollow ugc noopener\">benchmark source code</a> for details.</p></blockquote>\n<p>Of the four extensions, <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> exhibits the most consistent performance. <a href=\"https://github.com/duckdb/pg_duckdb\" rel=\"nofollow ugc noopener\">pg_duckdb</a> and <a href=\"https://github.com/Snowflake-Labs/pg_lake\" rel=\"nofollow ugc noopener\">pg_lake</a>, both backed by <a href=\"https://duckdb.org\" rel=\"nofollow ugc noopener\">DuckDB</a>, take around 2-3x as long to import data from CSV, JSON, and Parquet. Only <a href=\"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.S3Import.html\" rel=\"nofollow ugc noopener\">aws_s3</a> approaches <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a>&#39;s performance, but it supports a much more limited array of data formats.</p>\n<h2 id=\"data-formats\">Data formats</h2>\n<p>Did we mention data formats? The <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> extension can read and write a slew of data formats --- all those that <a href=\"https://clickhouse.com/docs/reference/formats/index\" rel=\"nofollow ugc noopener\">ClickHouse itself supports</a>. This table summarizes the supported data formats and compression algorithms of the extensions we compared; note that this <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> list of formats is but a subset of the <a href=\"https://clickhouse.com/docs/reference/formats/index\" rel=\"nofollow ugc noopener\">formats it supports</a>:</p>\n<div class=\"table-wrap\"><table><thead><tr><th>Extension</th><th>Compression</th><th>Data Formats</th></tr></thead><tbody><tr><td>aws_s3</td><td>none</td><td>Text (TSV), CSV, Postgres Binary</td></tr><tr><td>pg_lake</td><td>gzip, zstd, snappy (Parquet only)</td><td>CSV, JSON, Parquet</td></tr><tr><td>pg_duckdb</td><td>gzip, zstd, snappy (Parquet only)</td><td>CSV, JSON, Parquet</td></tr><tr><td>chdb</td><td>gzip, zstd, lz4, bz2, snappy, brotli</td><td>TSV, CSV, JSON, BSON, Prometheus, Protobuf, Avro, Parquet, Arrow, XML, CapnProto, Markdown, MsgPack, ORC, and <a href=\"https://clickhouse.com/docs/reference/formats/index\" rel=\"nofollow ugc noopener\">more</a>!</td></tr></tbody></table></div>\n<p>As <a href=\"https://github.com/ClickHouse/ClickHouse\" rel=\"nofollow ugc noopener\">ClickHouse</a> and the <a href=\"https://clickhouse.com/docs/chdb\" rel=\"nofollow ugc noopener\">chDB library</a> add more, the <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> extension will get them for free!</p>\n<p>We benchmarked <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> performance loading the <a href=\"https://clickhouse.com/docs/get-started/quickstarts/tutorial\" rel=\"nofollow ugc noopener\">NYC Taxi dataset</a> for a number of these formats, where it demonstrated quite consistent performance:</p>\n<p>We used the <a href=\"https://clickhouse.com/docs/reference/formats/JSON/JSONCompact\" rel=\"nofollow ugc noopener\">JSONCompact</a> format for compatibility with the other extensions. Other JSON formats, such as <a href=\"https://clickhouse.com/docs/reference/formats/JSON/JSONCompactEachRow\" rel=\"nofollow ugc noopener\">JSONCompactEachRow</a>, will more closely approximate the performance of the other formats.</p>\n<h2 id=\"usage\">Usage</h2>\n<p>The <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> package ships with two extensions: a <a href=\"https://www.postgresql.org/docs/current/sql-createextension.html\" rel=\"nofollow ugc noopener\">CREATE EXTENSION</a> extension named chdb and a <a href=\"https://wiki.postgresql.org/wiki/PostgresServerExtensionPoints#Hooks\" rel=\"nofollow ugc noopener\">hook module</a> named chdb_hook.</p>\n<h3 id=\"chdb-extension\">chdb extension</h3>\n<p>The chdb extension (<a href=\"https://pgxn.org/dist/chdb/doc/chdb.html\" rel=\"nofollow ugc noopener\">docs</a>) provides the <code>chdb_query()</code> function, which executes a single chDB query. For example, this query:</p>\n<pre><code>1SELECT * FROM chdb_query($$\n2  SELECT * FROM s3(&#39;s3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv&#39;);\n3$$) AS (id int, months int, days int);</code></pre>\n<p>Copy command</p>\n<p>Outputs:</p>\n<pre><code>1id | months | days\n2----+--------+------\n3  1 |      2 |    3\n4  3 |      2 |    1\n5  4 |      5 |    6\n6(3 rows)</code></pre>\n<p>Copy command</p>\n<h3 id=\"chdb-hook-module\">chdb_hook module</h3>\n<p>The <code>chdb_hook</code> module (<a href=\"https://pgxn.org/dist/chdb/doc/chdb_hook.html\" rel=\"nofollow ugc noopener\">docs</a>) hooks into the <a href=\"https://www.postgresql.org/docs/current/sql-copy.html\" rel=\"nofollow ugc noopener\">COPY</a> command to copy data to or from an <a href=\"https://aws.amazon.com/s3/\" rel=\"nofollow ugc noopener\">AWS S3</a>, <a href=\"https://cloud.google.com/storage\" rel=\"nofollow ugc noopener\">Google Cloud Storage</a>, <a href=\"https://azure.microsoft.com/en-us/products/storage/blobs/\" rel=\"nofollow ugc noopener\">Azure Blob Storage</a>, file, or http URL. This example loads records from a CSV file on S3:</p>\n<pre><code>1CREATE TABLE times (\n2    id     INT NOT NULL,\n3    months INT NOT NULL,\n4    days   INT NOT NULL\n5);\n6\n7LOAD &#39;chdb_hook&#39;;\n8COPY times FROM &#39;s3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv&#39;;</code></pre>\n<p>Copy command</p>\n<p>After which the <code>times</code> table contains the records from the file:</p>\n<pre><code>1# SELECT * FROM times;\n2 id | months | days\n3----+--------+------\n4  1 |      2 |    3\n5  3 |      2 |    1\n6  4 |      5 |    6\n7(3 rows)</code></pre>\n<p>Copy command</p>\n<p>A <a href=\"https://www.postgresql.org/docs/current/sql-createtable.html\" rel=\"nofollow ugc noopener\">CREATE TABLE</a> command may also derive its columns, and load its rows, from such a URL. Try this one (all the URLs in this piece point to legit data files):</p>\n<pre><code>1CREATE TABLE reviews () WITH (\n2    copy_from = &#39;s3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet&#39;\n3);</code></pre>\n<p>Copy command</p>\n<p>The resulting, fully-loaded table has this structure:</p>\n<div class=\"table-wrap\"><table><thead><tr><th>Column</th><th>Type</th></tr></thead><tbody><tr><td>review_date</td><td>integer</td></tr><tr><td>marketplace</td><td>text</td></tr><tr><td>customer_id</td><td>numeric(20,0)</td></tr><tr><td>review_id</td><td>text</td></tr><tr><td>product_id</td><td>text</td></tr><tr><td>product_parent</td><td>numeric(20,0)</td></tr><tr><td>product_title</td><td>text</td></tr><tr><td>product_category</td><td>text</td></tr><tr><td>star_rating</td><td>smallint</td></tr><tr><td>helpful_votes</td><td>bigint</td></tr><tr><td>total_votes</td><td>bigint</td></tr><tr><td>vine</td><td>boolean</td></tr><tr><td>verified_purchase</td><td>boolean</td></tr><tr><td>review_headline</td><td>text</td></tr><tr><td>review_body</td><td>text</td></tr></tbody></table></div>\n<h2 id=\"data-types\">Data types</h2>\n<p>Like <a href=\"https://clickhouse.com/docs/products/managed-postgres/extensions/pg_clickhouse/\" rel=\"nofollow ugc noopener\">pg_clickhouse</a>, <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> relies on the <a href=\"https://github.com/ClickHouse/pg-clickhouse-c/\" rel=\"nofollow ugc noopener\">pg-clickhouse-c</a> headers-only library to convert values from ClickHouse to Postgres, including its <a href=\"https://github.com/ClickHouse/pg-clickhouse-c/#type-mapping\" rel=\"nofollow ugc noopener\">type mapping</a>, as in the <code>CREATE TABLE</code> example above. The current release maps nearly all of the ClickHouse types to Postgres types and vice versa. These mappings work most of the time; when they don&#39;t, use the <code>structure</code> option to tell <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> what type to use.</p>\n<p>For example, <a href=\"https://github.com/ClickHouse/pg-clickhouse-c/\" rel=\"nofollow ugc noopener\">pg-clickhouse-c</a> maps a Postgres JSON value to ClickHouse String, because <a href=\"https://clickhouse.com/docs/reference/data-types/newjson\" rel=\"nofollow ugc noopener\">ClickHouse JSON</a> currently recognizes only JSON <em>objects</em> , while Postgres JSON supports objects, arrays, and JSON scalar values. But perhaps you&#39;re confident your JSON columns contain only objects, thanks to a check constraint:</p>\n<pre><code>1CREATE TABLE projects (\n2    name   TEXT PRIMARY KEY,\n3    meta   JSON NOT NULL CHECK (json_typeof(meta) = &#39;object&#39;)\n4);\n5\n6INSERT INTO projects\n7VALUES ( &#39;chdb&#39;,   &#39;{&quot;status&quot;: &quot;release&quot;}&#39; ),\n8       ( &#39;walrus&#39;, &#39;{&quot;status&quot;: &quot;revise&quot;}&#39;  );</code></pre>\n<p>Copy command</p>\n<p>To benefit from the increased flexibility and storage for object-aware storage formats such as <a href=\"https://parquet.apache.org/docs/file-format/types/logicaltypes/#json\" rel=\"nofollow ugc noopener\">Parquet JSON</a>, use the <code>structure</code> option to map it to <a href=\"https://clickhouse.com/docs/reference/data-types/newjson\" rel=\"nofollow ugc noopener\">ClickHouse JSON</a>:</p>\n<pre><code>1COPY projects to &#39;file:///tmp/projects.parquet&#39; (\n2    structure &#39;name String, meta JSON&#39;\n3);</code></pre>\n<p>Copy command</p>\n<h2 id=\"cloud-storage-urls\">Cloud storage URLs</h2>\n<p>The <a href=\"https://pgxn.org/dist/chdb/doc/chdb_hook.html\" rel=\"nofollow ugc noopener\">chdb_hook</a> extension reads and writes to all your favorite storage platforms. It determines the appropriate protocol from the URL scheme.</p>\n<div class=\"table-wrap\"><table><thead><tr><th>Schemes</th><th>Target</th></tr></thead><tbody><tr><td><code>file</code></td><td>Absolute path on the Postgres server</td></tr><tr><td><code>http</code>, <code>https</code></td><td>HTTP URL</td></tr><tr><td><code>s3</code></td><td><a href=\"https://aws.amazon.com/s3/\" rel=\"nofollow ugc noopener\">AWS S3</a></td></tr><tr><td><code>gs</code>, <code>gcs</code>, <code>oss</code></td><td><a href=\"https://cloud.google.com/storage\" rel=\"nofollow ugc noopener\">Google Cloud Storage</a></td></tr><tr><td><code>az</code>, <code>azure</code>, <code>abfss</code>, <code>abfs</code></td><td><a href=\"https://azure.microsoft.com/en-us/products/storage/blobs/\" rel=\"nofollow ugc noopener\">Azure Blob Storage</a> or <a href=\"https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction-abfs-uri\" rel=\"nofollow ugc noopener\">Azure ABFS</a></td></tr><tr><td><code>hdfs</code></td><td><a href=\"https://en.wikipedia.org/wiki/Apache_Hadoop#Overview\" rel=\"nofollow ugc noopener\">Hadoop Distributed File System</a></td></tr></tbody></table></div>\n<p>URLs may also use a number of <a href=\"https://pgxn.org/dist/chdb/doc/chdb_hook.html#Path.Wildcards\" rel=\"nofollow ugc noopener\">wildcards</a> to concurrently fetch multiple files. Revisiting the <code>CREATE TABLE</code> example above, this command finds and imports six files from S3:</p>\n<pre><code>1CREATE TABLE times () WITH (\n2    copy_from = &#39;s3://datasets-documentation/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv&#39;\n3);</code></pre>\n<p>Copy command</p>\n<p>After which the <code>times</code> table contains the records from each file it loaded:</p>\n<pre><code>1SELECT * FROM times;\n2 c1 | c2 | c3 \n3----+----+----\n4  1 |  2 |  3\n5  3 |  2 |  1\n6  4 |  5 |  6\n7  1 |  2 |  3\n8  3 |  2 |  1\n9  4 |  5 |  6\n10  1 |  2 |  3\n11  3 |  2 |  1\n12  4 |  5 |  6\n13  1 |  2 |  3\n14  3 |  2 |  1\n15  4 |  5 |  6\n16  1 |  2 |  3\n17  3 |  2 |  1\n18  4 |  5 |  6\n19  1 |  2 |  3\n20  3 |  2 |  1\n21  4 |  5 |  6\n22 (18 rows)</code></pre>\n<p>Copy command</p>\n<h2 id=\"architecture\">Architecture</h2>\n<p>Support for such a vast array of data formats and cloud platforms demands a panoply of dependencies. We avoid managing those dependencies by delegating the problem to the <a href=\"https://clickhouse.com/docs/chdb\" rel=\"nofollow ugc noopener\">chDB library</a>. But loading that library into a Postgres backend would be excessive, especially for typically occasional or periodic tasks such as loading from a data source once a day.</p>\n<p>Data loading extensions thus take a variety of approaches to managing the size and complexity of such a library by a variety of means:</p>\n<ul><li><a href=\"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.S3Import.html\" rel=\"nofollow ugc noopener\">aws_s3</a> simply downloads files to the local file system and passes control to <a href=\"https://www.postgresql.org/docs/current/sql-copy.html\" rel=\"nofollow ugc noopener\">COPY</a>; hence its limitation to <a href=\"https://aws.amazon.com/s3/\" rel=\"nofollow ugc noopener\">AWS S3</a> sources and the formats that Postgres <a href=\"https://www.postgresql.org/docs/current/sql-copy.html\" rel=\"nofollow ugc noopener\">COPY</a> supports</li><li><a href=\"https://github.com/duckdb/pg_duckdb\" rel=\"nofollow ugc noopener\">pg_duckdb</a> embeds the <a href=\"https://duckdb.org\" rel=\"nofollow ugc noopener\">DuckDB</a> engine in the Postgres backend, overkill for occasional <a href=\"https://www.postgresql.org/docs/current/sql-copy.html\" rel=\"nofollow ugc noopener\">COPY</a> needs</li><li><a href=\"https://github.com/Snowflake-Labs/pg_lake\" rel=\"nofollow ugc noopener\">pg_lake</a> runs a separate <a href=\"https://duckdb.org\" rel=\"nofollow ugc noopener\">DuckDB</a>-powered service and communicates with it via the <a href=\"https://www.postgresql.org/docs/current/libpq.html\" rel=\"nofollow ugc noopener\">libpq protocol</a>, which permanently consumes resources on the Postgres host</li></ul>\n<p>The <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb extension</a> adopts its own distinctive architecture: It embeds the <a href=\"https://clickhouse.com/docs/chdb\" rel=\"nofollow ugc noopener\">chDB library</a> into a separate helper application. Neither the extension nor <a href=\"https://pgxn.org/dist/chdb/doc/chdb_hook.html\" rel=\"nofollow ugc noopener\">chdb_hook</a> link chDB. Instead, they start the helper app on demand and communicate with it via an efficient, in-memory channel: file descriptors (<code>STDIN</code>, <code>STDOUT</code>, and <code>STDERR</code>, plus another for configuration information).</p>\n<p>This design prevents the <a href=\"https://clickhouse.com/docs/chdb\" rel=\"nofollow ugc noopener\">chDB library</a> from consuming any more resources than necessary to carry out a single command. It also isolates the PostgreSQL cluster itself from <a href=\"https://en.wikipedia.org/wiki/Out_of_memory\" rel=\"nofollow ugc noopener\">out of memory</a> issues that using shared memory with a <a href=\"https://www.postgresql.org/docs/current/bgworker.html\" rel=\"nofollow ugc noopener\">background worker</a> would suffer.</p>\n<p>When the helper app finishes executing a command and has passed all its results to the backend (in <a href=\"https://clickhouse.com/docs/reference/formats/Native\" rel=\"nofollow ugc noopener\">ClickHouse Native</a> format, straight from the source), it simply cleans up and exits, leaving the server resources to the service that most matters: PostgreSQL.</p>\n<pre><code>1+-------------+\n2                  |   helper    |\n3+----------+      |    app      |      +------+\n4| Postgres |      | +---------+ |      | chDB |\n5| Backend  |&lt;----&gt;| |  chDB   | |&lt;----&gt;| Data |\n6+----------+      | | Library | |      +------+\n7                  | +---------+ |\n8                  +-------------+</code></pre>\n<p>Copy command</p>\n<h2 id=\"what-s-next\">What&#39;s next?</h2>\n<p>We plan to continue making <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> better. Potential roadmap items include:</p>\n<ul><li>Complete type mapping. We&#39;re gradually filling in the gap between Postgres and ClickHouse data types, to the benefit of both <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> and <a href=\"https://clickhouse.com/docs/products/managed-postgres/extensions/pg_clickhouse/\" rel=\"nofollow ugc noopener\">pg_clickhouse</a>.</li><li>Access control to object storage via credential chain. Currently credentials required to read and write object stores must be passed explicitly in each <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb</a> call. We&#39;d like to allow transparent, server-configured credentialing to work as well.</li><li>Support for <code>COPY (query) TO</code></li><li>Support for a <code>WHERE</code> condition on <a href=\"https://www.postgresql.org/docs/current/sql-copy.html\" rel=\"nofollow ugc noopener\">COPY</a></li><li>Support for all of the existing <a href=\"https://www.postgresql.org/docs/current/sql-copy.html\" rel=\"nofollow ugc noopener\">COPY</a> options</li><li>Support for the <a href=\"https://iceberg.apache.org\" rel=\"nofollow ugc noopener\">Iceberg</a> format</li><li>Query files directly from storage</li></ul>\n<h2 id=\"give-it-a-try\">Give it a try</h2>\n<p>Find the <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">chdb extension</a> in all the usual places, including <a href=\"https://github.com/ClickHouse/pg_chdb\" rel=\"nofollow ugc noopener\">GitHub</a> and <a href=\"https://pgxn.org/dist/chdb/\" rel=\"nofollow ugc noopener\">PGXN</a>. We also provide it as part of the broader <a href=\"https://clickhouse.com/docs/products/managed-postgres/extensions/pg_clickhouse/\" rel=\"nofollow ugc noopener\">pg_clickhouse</a> package on <a href=\"https://clickhouse.com/cloud/postgres\" rel=\"nofollow ugc noopener\">ClickHouse Managed Postgres</a>; ask your support contact to add <code>chdb_hook</code> to your default configuration, or just connect to a superuser account via <code>psql</code> or your favorite client, run <code>CREATE EXTENSION chdb;</code> or <code>LOAD &#39;chdb_hook&#39;;</code> and get started!</p>\n<h3 id=\"get-started-with-clickhouse-managed-postgres-today\">Get started with ClickHouse Managed Postgres today</h3>\n<p>Interested in seeing how ClickHouse Managed Postgres works on your data? Get started with ClickHouse Cloud in minutes and receive $300 in free credits.</p>\n<p><a href=\"https://console.clickhouse.cloud/signUp?intent=pg&amp;loc=blog-cta-1837-get-started-with-clickhouse-managed-postgres-today-sign-up&amp;utm_blogctaid=1837\" rel=\"nofollow ugc noopener\">Sign up</a></p>","headings":[{"level":2,"text":"Benchmark","id":"benchmark"},{"level":2,"text":"Data formats","id":"data-formats"},{"level":2,"text":"Usage","id":"usage"},{"level":3,"text":"chdb extension","id":"chdb-extension"},{"level":3,"text":"chdb_hook module","id":"chdb-hook-module"},{"level":2,"text":"Data types","id":"data-types"},{"level":2,"text":"Cloud storage URLs","id":"cloud-storage-urls"},{"level":2,"text":"Architecture","id":"architecture"},{"level":2,"text":"What's next?","id":"what-s-next"},{"level":2,"text":"Give it a try","id":"give-it-a-try"},{"level":3,"text":"Get started with ClickHouse Managed Postgres today","id":"get-started-with-clickhouse-managed-postgres-today"}]}}