Export ClickHouse data and import it into MySQL while preserving schema, data types, and indexes.
Dump each ClickHouse table to CSV or Parquet, recreate the schema in MySQL, and bulk-load with LOAD DATA INFILE
. This minimizes network chatter and leverages both engines’ bulk I/O performance.
Use clickhouse-client
with SELECT ... FORMAT CSV
piped to a file. Add --max_insert_threads
to parallelize and --allow_experimental_parallel_reading_from_replicas=1
for larger datasets.
$ clickhouse-client --query="SELECT * FROM Orders FORMAT CSV" > orders.csv
Match ClickHouse types to MySQL equivalents: Int32 ➜ INT
, Float64 ➜ DOUBLE
, DateTime64 ➜ DATETIME(6)
. Create indexes after data load to speed up imports.
CREATE TABLE Orders( id INT PRIMARY KEY, customer_id INT, order_date DATETIME, total_amount DECIMAL(10,2) );
Enable LOCAL
option if the file sits on the client. Disable foreign-key checks during load for speed.
SET FOREIGN_KEY_CHECKS=0;\nLOAD DATA LOCAL INFILE 'orders.csv' INTO TABLE Orders\nFIELDS TERMINATED BY ',' ENCLOSED BY '"'\nLINES TERMINATED BY '\n'\n(id, customer_id, order_date, total_amount);\nSET FOREIGN_KEY_CHECKS=1;
Export and import tables in dependency order: Customers → Products → Orders → OrderItems
. Validate row counts after each load.
Count rows, verify sums (e.g., SUM(total_amount)
), and sample records in both systems. Automate checks with a script.
Run migrations off-peak, snapshot ClickHouse tables to avoid mutations during export, and keep retryable scripts in version control. Test in staging before production.
Use open-source tools like Airbyte or custom scripts; no first-party replication exists.
Yes—split exports by date range and parallelize ClickHouse reads; compress files before transfer.