From a7d0b3acbd16864fe9c6da59c32e60f38c489e98 Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Tue, 14 Jan 2025 10:10:44 -0500 Subject: [PATCH 01/10] move Migrating from Snowflake moved Migrating from Snowflake to Migrating from Databases. --- docs/en/tutorials/migrate/_category_.json | 3 +++ .../en/tutorials/{load => migrate}/migrating-from-snowflake.md | 0 2 files changed, 3 insertions(+) create mode 100644 docs/en/tutorials/migrate/_category_.json rename docs/en/tutorials/{load => migrate}/migrating-from-snowflake.md (100%) diff --git a/docs/en/tutorials/migrate/_category_.json b/docs/en/tutorials/migrate/_category_.json new file mode 100644 index 0000000000..5224f7ca97 --- /dev/null +++ b/docs/en/tutorials/migrate/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Migrating from Databases" +} \ No newline at end of file diff --git a/docs/en/tutorials/load/migrating-from-snowflake.md b/docs/en/tutorials/migrate/migrating-from-snowflake.md similarity index 100% rename from docs/en/tutorials/load/migrating-from-snowflake.md rename to docs/en/tutorials/migrate/migrating-from-snowflake.md From 10196ab77c6cf681fa32a49b2c891b360a3b50e6 Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Tue, 14 Jan 2025 10:28:00 -0500 Subject: [PATCH 02/10] Migrating from MySQL with Addax --- .../guides/40-load-data/02-load-db/addax.md | 101 +---------------- .../migrating-from-mysql-with-addax.md | 103 ++++++++++++++++++ 2 files changed, 105 insertions(+), 99 deletions(-) create mode 100644 docs/en/tutorials/migrate/migrating-from-mysql-with-addax.md diff --git a/docs/en/guides/40-load-data/02-load-db/addax.md b/docs/en/guides/40-load-data/02-load-db/addax.md index 47f82a8022..2bf8c2c8b0 100644 --- a/docs/en/guides/40-load-data/02-load-db/addax.md +++ b/docs/en/guides/40-load-data/02-load-db/addax.md @@ -18,104 +18,7 @@ DatabendReader and DatabendWriter are integrated plugins of Addax, allowing seam The DatabendReader plugin enables reading data from Databend. Databend provides compatibility with the MySQL client protocol, so you can also use the [MySQLReader](https://wgzhao.github.io/Addax/develop/reader/mysqlreader/) plugin to retrieve data from Databend. For more information about DatabendReader, see https://wgzhao.github.io/Addax/develop/reader/databendreader/ -## Tutorial: Data Loading from MySQL +## Tutorials -In this tutorial, you will load data from MySQL to Databend with Addax. Before you start, make sure you have successfully set up Databend, MySQL, and Addax in your environment. +- [Migrating from MySQL with Addax](/tutorials/migrate/migrating-from-mysql-with-addax) -1. In MySQL, create a SQL user that you will use for data loading and then create a table and populate it with sample data. - -```sql title='In MySQL:' -mysql> create user 'mysqlu1'@'%' identified by '123'; -mysql> grant all on *.* to 'mysqlu1'@'%'; -mysql> create database db; -mysql> create table db.tb01(id int, col1 varchar(10)); -mysql> insert into db.tb01 values(1, 'test1'), (2, 'test2'), (3, 'test3'); -``` - -2. In Databend, create a corresponding target table. - -```sql title='In Databend:' -databend> create database migrated_db; -databend> create table migrated_db.tb01(id int null, col1 String null); -``` - -3. Copy and paste the following code to a file, and name the file as *mysql_demo.json*: - -:::note -For the available parameters and their descriptions, refer to the documentation provided at the following link: https://wgzhao.github.io/Addax/develop/writer/databendwriter/#_2 -::: - -```json title='mysql_demo.json' -{ - "job": { - "setting": { - "speed": { - "channel": 4 - } - }, - "content": { - "writer": { - "name": "databendwriter", - "parameter": { - "preSql": [ - "truncate table @table" - ], - "postSql": [ - ], - "username": "u1", - "password": "123", - "database": "migrate_db", - "table": "tb01", - "jdbcUrl": "jdbc:mysql://127.0.0.1:3307/migrated_db", - "loadUrl": ["127.0.0.1:8000","127.0.0.1:8000"], - "fieldDelimiter": "\\x01", - "lineDelimiter": "\\x02", - "column": ["*"], - "format": "csv" - } - }, - "reader": { - "name": "mysqlreader", - "parameter": { - "username": "mysqlu1", - "password": "123", - "column": [ - "*" - ], - "connection": [ - { - "jdbcUrl": [ - "jdbc:mysql://127.0.0.1:3306/db" - ], - "driver": "com.mysql.jdbc.Driver", - "table": [ - "tb01" - ] - } - ] - } - } - } - } -} -``` - -4. Run Addax: - -```shell -cd {YOUR_ADDAX_DIR_BIN} -./addax.sh -L debug ./mysql_demo.json -``` - -You're all set! To verify the data loading, execute the query in Databend: - -```sql -databend> select * from migrated_db.tb01; -+------+-------+ -| id | col1 | -+------+-------+ -| 1 | test1 | -| 2 | test2 | -| 3 | test3 | -+------+-------+ -``` \ No newline at end of file diff --git a/docs/en/tutorials/migrate/migrating-from-mysql-with-addax.md b/docs/en/tutorials/migrate/migrating-from-mysql-with-addax.md new file mode 100644 index 0000000000..910e2efcd1 --- /dev/null +++ b/docs/en/tutorials/migrate/migrating-from-mysql-with-addax.md @@ -0,0 +1,103 @@ +--- +title: Migrating from MySQL with Addax +--- + +In this tutorial, you will load data from MySQL to Databend with Addax. Before you start, make sure you have successfully set up Databend, MySQL, and Addax in your environment. + +1. In MySQL, create a SQL user that you will use for data loading and then create a table and populate it with sample data. + +```sql title='In MySQL:' +mysql> create user 'mysqlu1'@'%' identified by '123'; +mysql> grant all on *.* to 'mysqlu1'@'%'; +mysql> create database db; +mysql> create table db.tb01(id int, col1 varchar(10)); +mysql> insert into db.tb01 values(1, 'test1'), (2, 'test2'), (3, 'test3'); +``` + +2. In Databend, create a corresponding target table. + +```sql title='In Databend:' +databend> create database migrated_db; +databend> create table migrated_db.tb01(id int null, col1 String null); +``` + +3. Copy and paste the following code to a file, and name the file as *mysql_demo.json*: + +:::note +For the available parameters and their descriptions, refer to the documentation provided at the following link: https://wgzhao.github.io/Addax/develop/writer/databendwriter/#_2 +::: + +```json title='mysql_demo.json' +{ + "job": { + "setting": { + "speed": { + "channel": 4 + } + }, + "content": { + "writer": { + "name": "databendwriter", + "parameter": { + "preSql": [ + "truncate table @table" + ], + "postSql": [ + ], + "username": "u1", + "password": "123", + "database": "migrate_db", + "table": "tb01", + "jdbcUrl": "jdbc:mysql://127.0.0.1:3307/migrated_db", + "loadUrl": ["127.0.0.1:8000","127.0.0.1:8000"], + "fieldDelimiter": "\\x01", + "lineDelimiter": "\\x02", + "column": ["*"], + "format": "csv" + } + }, + "reader": { + "name": "mysqlreader", + "parameter": { + "username": "mysqlu1", + "password": "123", + "column": [ + "*" + ], + "connection": [ + { + "jdbcUrl": [ + "jdbc:mysql://127.0.0.1:3306/db" + ], + "driver": "com.mysql.jdbc.Driver", + "table": [ + "tb01" + ] + } + ] + } + } + } + } +} +``` + +4. Run Addax: + +```shell +cd {YOUR_ADDAX_DIR_BIN} +./addax.sh -L debug ./mysql_demo.json +``` + +You're all set! To verify the data loading, execute the query in Databend: + +```sql +databend> select * from migrated_db.tb01; ++------+-------+ +| id | col1 | ++------+-------+ +| 1 | test1 | +| 2 | test2 | +| 3 | test3 | ++------+-------+ +``` \ No newline at end of file From 4871cc727bcd2a68f0ccb340a0d480169718b6e1 Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Tue, 14 Jan 2025 12:56:40 -0500 Subject: [PATCH 03/10] Migrating from MySQL with DataX --- .../guides/40-load-data/02-load-db/datax.md | 120 +---------------- .../migrating-from-mysql-with-datax.md | 121 ++++++++++++++++++ 2 files changed, 123 insertions(+), 118 deletions(-) create mode 100644 docs/en/tutorials/migrate/migrating-from-mysql-with-datax.md diff --git a/docs/en/guides/40-load-data/02-load-db/datax.md b/docs/en/guides/40-load-data/02-load-db/datax.md index 7fb582ec13..7d1b0fb7a8 100644 --- a/docs/en/guides/40-load-data/02-load-db/datax.md +++ b/docs/en/guides/40-load-data/02-load-db/datax.md @@ -24,122 +24,6 @@ DatabendWriter supports two operational modes: INSERT (default) and REPLACE. In If you need more information about DatabendWriter and its functionalities, you can refer to the documentation available at https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md -## Tutorial: Data Loading from MySQL +## Tutorials -In this tutorial, you will load data from MySQL to Databend with DataX. Before you start, make sure you have successfully set up Databend, MySQL, and DataX in your environment. - -1. In MySQL, create a SQL user that you will use for data loading and then create a table and populate it with sample data. - -```sql title='In MySQL:' -mysql> create user 'mysqlu1'@'%' identified by 'databend'; -mysql> grant all on *.* to 'mysqlu1'@'%'; -mysql> create database db; -mysql> create table db.tb01(id int, d double, t TIMESTAMP, col1 varchar(10)); -mysql> insert into db.tb01 values(1, 3.1,now(), 'test1'), (1, 4.1,now(), 'test2'), (1, 4.1,now(), 'test2'); -``` - -2. In Databend, create a corresponding target table. - -:::note -DataX data types can be converted to Databend's data types when loaded into Databend. For the specific correspondences between DataX data types and Databend's data types, refer to the documentation provided at the following link: https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md#33-type-convert -::: - -```sql title='In Databend:' -databend> create database migrated_db; -databend> create table migrated_db.tb01(id int null, d double null, t TIMESTAMP null, col1 varchar(10) null); -``` - -3. Copy and paste the following code to a file, and name the file as *mysql_demo.json*. For the available parameters and their descriptions, refer to the documentation provided at the following link: https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md#32-configuration-description - -```json title='mysql_demo.json' -{ - "job": { - "content": [ - { - "reader": { - "name": "mysqlreader", - "parameter": { - "username": "mysqlu1", - "password": "databend", - "column": [ - "id", "d", "t", "col1" - ], - "connection": [ - { - "jdbcUrl": [ - "jdbc:mysql://127.0.0.1:3307/db" - ], - "driver": "com.mysql.jdbc.Driver", - "table": [ - "tb01" - ] - } - ] - } - }, - "writer": { - "name": "databendwriter", - "parameter": { - "username": "databend", - "password": "databend", - "column": [ - "id", "d", "t", "col1" - ], - "preSql": [ - ], - "postSql": [ - ], - "connection": [ - { - "jdbcUrl": "jdbc:databend://localhost:8000/migrated_db", - "table": [ - "tb01" - ] - } - ] - } - } - } - ], - "setting": { - "speed": { - "channel": 1 - } - } - } -} -``` - -:::tip -The provided code above configures DatabendWriter to operate in the INSERT mode. To switch to the REPLACE mode, you must include the writeMode and onConflictColumn parameters. For example: - -```json title='mysql_demo.json' -... -"writer": { - "name": "databendwriter", - "parameter": { - "writeMode": "replace", - "onConflictColumn":["id"], - "username": ... -``` -::: - -4. Run DataX: - -```shell -cd {YOUR_DATAX_DIR_BIN} -python datax.py ./mysql_demo.json -``` - -You're all set! To verify the data loading, execute the query in Databend: - -```sql -databend> select * from migrated_db.tb01; -+------+------+----------------------------+-------+ -| id | d | t | col1 | -+------+------+----------------------------+-------+ -| 1 | 3.1 | 2023-02-01 07:11:08.500000 | test1 | -| 1 | 4.1 | 2023-02-01 07:11:08.501000 | test2 | -| 1 | 4.1 | 2023-02-01 07:11:08.501000 | test2 | -+------+------+----------------------------+-------+ -``` \ No newline at end of file +- [Migrating from MySQL with DataX](/tutorials/migrate/migrating-from-mysql-with-datax) \ No newline at end of file diff --git a/docs/en/tutorials/migrate/migrating-from-mysql-with-datax.md b/docs/en/tutorials/migrate/migrating-from-mysql-with-datax.md new file mode 100644 index 0000000000..d3f14f8223 --- /dev/null +++ b/docs/en/tutorials/migrate/migrating-from-mysql-with-datax.md @@ -0,0 +1,121 @@ +--- +title: Migrating from MySQL with DataX +--- + +In this tutorial, you will load data from MySQL to Databend with DataX. Before you start, make sure you have successfully set up Databend, MySQL, and DataX in your environment. + +1. In MySQL, create a SQL user that you will use for data loading and then create a table and populate it with sample data. + +```sql title='In MySQL:' +mysql> create user 'mysqlu1'@'%' identified by 'databend'; +mysql> grant all on *.* to 'mysqlu1'@'%'; +mysql> create database db; +mysql> create table db.tb01(id int, d double, t TIMESTAMP, col1 varchar(10)); +mysql> insert into db.tb01 values(1, 3.1,now(), 'test1'), (1, 4.1,now(), 'test2'), (1, 4.1,now(), 'test2'); +``` + +2. In Databend, create a corresponding target table. + +:::note +DataX data types can be converted to Databend's data types when loaded into Databend. For the specific correspondences between DataX data types and Databend's data types, refer to the documentation provided at the following link: https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md#33-type-convert +::: + +```sql title='In Databend:' +databend> create database migrated_db; +databend> create table migrated_db.tb01(id int null, d double null, t TIMESTAMP null, col1 varchar(10) null); +``` + +3. Copy and paste the following code to a file, and name the file as *mysql_demo.json*. For the available parameters and their descriptions, refer to the documentation provided at the following link: https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md#32-configuration-description + +```json title='mysql_demo.json' +{ + "job": { + "content": [ + { + "reader": { + "name": "mysqlreader", + "parameter": { + "username": "mysqlu1", + "password": "databend", + "column": [ + "id", "d", "t", "col1" + ], + "connection": [ + { + "jdbcUrl": [ + "jdbc:mysql://127.0.0.1:3307/db" + ], + "driver": "com.mysql.jdbc.Driver", + "table": [ + "tb01" + ] + } + ] + } + }, + "writer": { + "name": "databendwriter", + "parameter": { + "username": "databend", + "password": "databend", + "column": [ + "id", "d", "t", "col1" + ], + "preSql": [ + ], + "postSql": [ + ], + "connection": [ + { + "jdbcUrl": "jdbc:databend://localhost:8000/migrated_db", + "table": [ + "tb01" + ] + } + ] + } + } + } + ], + "setting": { + "speed": { + "channel": 1 + } + } + } +} +``` + +:::tip +The provided code above configures DatabendWriter to operate in the INSERT mode. To switch to the REPLACE mode, you must include the writeMode and onConflictColumn parameters. For example: + +```json title='mysql_demo.json' +... +"writer": { + "name": "databendwriter", + "parameter": { + "writeMode": "replace", + "onConflictColumn":["id"], + "username": ... +``` +::: + +4. Run DataX: + +```shell +cd {YOUR_DATAX_DIR_BIN} +python datax.py ./mysql_demo.json +``` + +You're all set! To verify the data loading, execute the query in Databend: + +```sql +databend> select * from migrated_db.tb01; ++------+------+----------------------------+-------+ +| id | d | t | col1 | ++------+------+----------------------------+-------+ +| 1 | 3.1 | 2023-02-01 07:11:08.500000 | test1 | +| 1 | 4.1 | 2023-02-01 07:11:08.501000 | test2 | +| 1 | 4.1 | 2023-02-01 07:11:08.501000 | test2 | ++------+------+----------------------------+-------+ +``` \ No newline at end of file From f46d680e12482d2d461631d60e375fadc3926cae Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Tue, 14 Jan 2025 15:46:24 -0500 Subject: [PATCH 04/10] Migrating from MySQL with Debezium --- .../40-load-data/02-load-db/debezium.md | 90 +----------------- .../migrating-from-mysql-with-debezium.md | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+), 88 deletions(-) create mode 100644 docs/en/tutorials/migrate/migrating-from-mysql-with-debezium.md diff --git a/docs/en/guides/40-load-data/02-load-db/debezium.md b/docs/en/guides/40-load-data/02-load-db/debezium.md index 56a230e5a1..ee5865819d 100644 --- a/docs/en/guides/40-load-data/02-load-db/debezium.md +++ b/docs/en/guides/40-load-data/02-load-db/debezium.md @@ -89,92 +89,6 @@ services: docker-compose up -d ``` -## Usage Example +## Tutorials -This section demonstrates the general steps to load data from MySQL into Databend and assumes that you already have a local MySQL instance running. - -### Step 1. Prepare Data in MySQL - -Create a database and a table in MySQL, and insert sample data into the table. - -```sql -CREATE DATABASE mydb; -USE mydb; - -CREATE TABLE products (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,description VARCHAR(512)); -ALTER TABLE products AUTO_INCREMENT = 10; - -INSERT INTO products VALUES (default,"scooter","Small 2-wheel scooter"), -(default,"car battery","12V car battery"), -(default,"12-pack drill bits","12-pack of drill bits with sizes ranging from #40 to #3"), -(default,"hammer","12oz carpenter's hammer"), -(default,"hammer","14oz carpenter's hammer"), -(default,"hammer","16oz carpenter's hammer"), -(default,"rocks","box of assorted rocks"), -(default,"jacket","water-proof black wind breaker"), -(default,"cloud","test for databend"), -(default,"spare tire","24 inch spare tire"); -``` - -### Step 2. Create database in Databend - -Create the corresponding database in Databend. Please note that you don't need to create a table that corresponds to the one in MySQL. - -```sql -CREATE DATABASE debezium; -``` - -### Step 3. Create application.properties - -Create the file _application.properties_, then start debezium-server-databend. For how to install and start the tool, see [Installing debezium-server-databend](#installing-debezium-server-databend). - -When started for the first time, the tool performs a full synchronization of data from MySQL to Databend using the specified Batch Size. As a result, the data from MySQL is now visible in Databend after successful replication. - -```text title='application.properties' -debezium.sink.type=databend -debezium.sink.databend.upsert=true -debezium.sink.databend.upsert-keep-deletes=false -debezium.sink.databend.database.databaseName=debezium -debezium.sink.databend.database.url=jdbc:databend://: -debezium.sink.databend.database.username= -debezium.sink.databend.database.password= -debezium.sink.databend.database.primaryKey=id -debezium.sink.databend.database.tableName=products -debezium.sink.databend.database.param.ssl=true - -# enable event schemas -debezium.format.value.schemas.enable=true -debezium.format.key.schemas.enable=true -debezium.format.value=json -debezium.format.key=json - -# mysql source -debezium.source.connector.class=io.debezium.connector.mysql.MySqlConnector -debezium.source.offset.storage.file.filename=data/offsets.dat -debezium.source.offset.flush.interval.ms=60000 - -debezium.source.database.hostname=127.0.0.1 -debezium.source.database.port=3306 -debezium.source.database.user=root -debezium.source.database.password=123456 -debezium.source.database.dbname=mydb -debezium.source.database.server.name=from_mysql -debezium.source.include.schema.changes=false -debezium.source.table.include.list=mydb.products -# debezium.source.database.ssl.mode=required -# Run without Kafka, use local file to store checkpoints -debezium.source.database.history=io.debezium.relational.history.FileDatabaseHistory -debezium.source.database.history.file.filename=data/status.dat -# do event flattening. unwrap message! -debezium.transforms=unwrap -debezium.transforms.unwrap.type=io.debezium.transforms.ExtractNewRecordState -debezium.transforms.unwrap.delete.handling.mode=rewrite -debezium.transforms.unwrap.drop.tombstones=true - -# ############ SET LOG LEVELS ############ -quarkus.log.level=INFO -# Ignore messages below warning level from Jetty, because it's a bit verbose -quarkus.log.category."org.eclipse.jetty".level=WARN -``` - -You're all set! If you query the products table in Databend, you will see that the data from MySQL has been successfully synchronized. Feel free to perform insertions, updates, or deletions in MySQL, and you will observe the corresponding changes reflected in Databend as well. +- [Migrating from MySQL with Debezium](/tutorials/migrate/migrating-from-mysql-with-debezium) \ No newline at end of file diff --git a/docs/en/tutorials/migrate/migrating-from-mysql-with-debezium.md b/docs/en/tutorials/migrate/migrating-from-mysql-with-debezium.md new file mode 100644 index 0000000000..3cb2caa569 --- /dev/null +++ b/docs/en/tutorials/migrate/migrating-from-mysql-with-debezium.md @@ -0,0 +1,91 @@ +--- +title: Migrating from MySQL with Debezium +--- + +In this tutorial, you will load data from MySQL to Databend with Debezium. Before you start, make sure you have successfully set up Databend, MySQL, and Debezium in your environment. + +## Step 1. Prepare Data in MySQL + +Create a database and a table in MySQL, and insert sample data into the table. + +```sql +CREATE DATABASE mydb; +USE mydb; + +CREATE TABLE products (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,description VARCHAR(512)); +ALTER TABLE products AUTO_INCREMENT = 10; + +INSERT INTO products VALUES (default,"scooter","Small 2-wheel scooter"), +(default,"car battery","12V car battery"), +(default,"12-pack drill bits","12-pack of drill bits with sizes ranging from #40 to #3"), +(default,"hammer","12oz carpenter's hammer"), +(default,"hammer","14oz carpenter's hammer"), +(default,"hammer","16oz carpenter's hammer"), +(default,"rocks","box of assorted rocks"), +(default,"jacket","water-proof black wind breaker"), +(default,"cloud","test for databend"), +(default,"spare tire","24 inch spare tire"); +``` + +## Step 2. Create database in Databend + +Create the corresponding database in Databend. Please note that you don't need to create a table that corresponds to the one in MySQL. + +```sql +CREATE DATABASE debezium; +``` + +## Step 3. Create application.properties + +Create the file _application.properties_, then start debezium-server-databend. For how to install and start the tool, see [Installing debezium-server-databend](#installing-debezium-server-databend). + +When started for the first time, the tool performs a full synchronization of data from MySQL to Databend using the specified Batch Size. As a result, the data from MySQL is now visible in Databend after successful replication. + +```text title='application.properties' +debezium.sink.type=databend +debezium.sink.databend.upsert=true +debezium.sink.databend.upsert-keep-deletes=false +debezium.sink.databend.database.databaseName=debezium +debezium.sink.databend.database.url=jdbc:databend://: +debezium.sink.databend.database.username= +debezium.sink.databend.database.password= +debezium.sink.databend.database.primaryKey=id +debezium.sink.databend.database.tableName=products +debezium.sink.databend.database.param.ssl=true + +# enable event schemas +debezium.format.value.schemas.enable=true +debezium.format.key.schemas.enable=true +debezium.format.value=json +debezium.format.key=json + +# mysql source +debezium.source.connector.class=io.debezium.connector.mysql.MySqlConnector +debezium.source.offset.storage.file.filename=data/offsets.dat +debezium.source.offset.flush.interval.ms=60000 + +debezium.source.database.hostname=127.0.0.1 +debezium.source.database.port=3306 +debezium.source.database.user=root +debezium.source.database.password=123456 +debezium.source.database.dbname=mydb +debezium.source.database.server.name=from_mysql +debezium.source.include.schema.changes=false +debezium.source.table.include.list=mydb.products +# debezium.source.database.ssl.mode=required +# Run without Kafka, use local file to store checkpoints +debezium.source.database.history=io.debezium.relational.history.FileDatabaseHistory +debezium.source.database.history.file.filename=data/status.dat +# do event flattening. unwrap message! +debezium.transforms=unwrap +debezium.transforms.unwrap.type=io.debezium.transforms.ExtractNewRecordState +debezium.transforms.unwrap.delete.handling.mode=rewrite +debezium.transforms.unwrap.drop.tombstones=true + +# ############ SET LOG LEVELS ############ +quarkus.log.level=INFO +# Ignore messages below warning level from Jetty, because it's a bit verbose +quarkus.log.category."org.eclipse.jetty".level=WARN +``` + +You're all set! If you query the products table in Databend, you will see that the data from MySQL has been successfully synchronized. Feel free to perform insertions, updates, or deletions in MySQL, and you will observe the corresponding changes reflected in Databend as well. \ No newline at end of file From 83270801f68a292c9645d2c29e542688a09ef898 Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Tue, 14 Jan 2025 20:18:47 -0500 Subject: [PATCH 05/10] Migrating from MySQL with Flink CDC --- .../40-load-data/02-load-db/flink-cdc.md | 139 +---------------- .../migrating-from-mysql-with-flink-cdc.md | 140 ++++++++++++++++++ 2 files changed, 142 insertions(+), 137 deletions(-) create mode 100644 docs/en/tutorials/migrate/migrating-from-mysql-with-flink-cdc.md diff --git a/docs/en/guides/40-load-data/02-load-db/flink-cdc.md b/docs/en/guides/40-load-data/02-load-db/flink-cdc.md index 037be78241..6c8a632e0e 100644 --- a/docs/en/guides/40-load-data/02-load-db/flink-cdc.md +++ b/docs/en/guides/40-load-data/02-load-db/flink-cdc.md @@ -26,141 +26,6 @@ To download and install the Flink SQL connector for Databend, follow these steps 3. Move the JAR file: Once you have downloaded the connector, move the JAR file to the lib folder in your Flink installation directory. For example, if you have Flink version 1.16.0 installed, move the JAR file to the flink-1.16.0/lib/ directory. -## Tutorial: Real-time Data Loading from MySQL +## Tutorials -In this tutorial, you will set up a real-time data loading from MySQL to Databend with the Flink SQL connector for Databend. Before you start, make sure you have successfully set up Databend and MySQL in your environment. - -1. Create a table in MySQL and populate it with sample data. Then, create a corresponding target table in Databend. - -```sql title='In MySQL:' -CREATE DATABASE mydb; -USE mydb; - -CREATE TABLE products (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,description VARCHAR(512)); -ALTER TABLE products AUTO_INCREMENT = 10; - -INSERT INTO products VALUES (default,"scooter","Small 2-wheel scooter"), -(default,"car battery","12V car battery"), -(default,"12-pack drill bits","12-pack of drill bits with sizes ranging from #40 to #3"), -(default,"hammer","12oz carpenter's hammer"), -(default,"hammer","14oz carpenter's hammer"), -(default,"hammer","16oz carpenter's hammer"), -(default,"rocks","box of assorted rocks"), -(default,"jacket","black wind breaker"), -(default,"cloud","test for databend"), -(default,"spare tire","24 inch spare tire"); -``` - -```sql title='In Databend:' -CREATE TABLE products (id INT NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(512) ); -``` - -2. Download [Flink](https://flink.apache.org/downloads/) and the following SQL connectors to your system: - - Flink SQL connector for Databend: [https://github.com/databendcloud/flink-connector-databend/releases](https://github.com/databendcloud/flink-connector-databend/releases) - - Flink SQL connector for MySQL: [https://repo1.maven.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/2.3.0/flink-sql-connector-mysql-cdc-2.3.0.jar](https://repo1.maven.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/2.3.0/flink-sql-connector-mysql-cdc-2.3.0.jar) -3. Move the both connector JAR files to the _lib_ folder in your Flink installation directory. -4. Start Flink: - -```shell -cd flink-16.0 -./bin/start-cluster.sh -``` - -You can now open the Apache Flink Dashboard if you go to [http://localhost:8081](http://localhost:8081) in your browser: - -![Alt text](/img/load/cdc-dashboard.png) - -5. Start the Flink SQL Client: - -```shell -./bin/sql-client.sh - - ▒▓██▓██▒ - ▓████▒▒█▓▒▓███▓▒ - ▓███▓░░ ▒▒▒▓██▒ ▒ - ░██▒ ▒▒▓▓█▓▓▒░ ▒████ - ██▒ ░▒▓███▒ ▒█▒█▒ - ░▓█ ███ ▓░▒██ - ▓█ ▒▒▒▒▒▓██▓░▒░▓▓█ - █░ █ ▒▒░ ███▓▓█ ▒█▒▒▒ - ████░ ▒▓█▓ ██▒▒▒ ▓███▒ - ░▒█▓▓██ ▓█▒ ▓█▒▓██▓ ░█░ - ▓░▒▓████▒ ██ ▒█ █▓░▒█▒░▒█▒ - ███▓░██▓ ▓█ █ █▓ ▒▓█▓▓█▒ - ░██▓ ░█░ █ █▒ ▒█████▓▒ ██▓░▒ - ███░ ░ █░ ▓ ░█ █████▒░░ ░█░▓ ▓░ - ██▓█ ▒▒▓▒ ▓███████▓░ ▒█▒ ▒▓ ▓██▓ - ▒██▓ ▓█ █▓█ ░▒█████▓▓▒░ ██▒▒ █ ▒ ▓█▒ - ▓█▓ ▓█ ██▓ ░▓▓▓▓▓▓▓▒ ▒██▓ ░█▒ - ▓█ █ ▓███▓▒░ ░▓▓▓███▓ ░▒░ ▓█ - ██▓ ██▒ ░▒▓▓███▓▓▓▓▓██████▓▒ ▓███ █ - ▓███▒ ███ ░▓▓▒░░ ░▓████▓░ ░▒▓▒ █▓ - █▓▒▒▓▓██ ░▒▒░░░▒▒▒▒▓██▓░ █▓ - ██ ▓░▒█ ▓▓▓▓▒░░ ▒█▓ ▒▓▓██▓ ▓▒ ▒▒▓ - ▓█▓ ▓▒█ █▓░ ░▒▓▓██▒ ░▓█▒ ▒▒▒░▒▒▓█████▒ - ██░ ▓█▒█▒ ▒▓▓▒ ▓█ █░ ░░░░ ░█▒ - ▓█ ▒█▓ ░ █░ ▒█ █▓ - █▓ ██ █░ ▓▓ ▒█▓▓▓▒█░ - █▓ ░▓██░ ▓▒ ▓█▓▒░░░▒▓█░ ▒█ - ██ ▓█▓░ ▒ ░▒█▒██▒ ▓▓ - ▓█▒ ▒█▓▒░ ▒▒ █▒█▓▒▒░░▒██ - ░██▒ ▒▓▓▒ ▓██▓▒█▒ ░▓▓▓▓▒█▓ - ░▓██▒ ▓░ ▒█▓█ ░░▒▒▒ - ▒▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░▓▓ ▓░▒█░ - - ______ _ _ _ _____ ____ _ _____ _ _ _ BETA - | ____| (_) | | / ____|/ __ \| | / ____| (_) | | - | |__ | |_ _ __ | | __ | (___ | | | | | | | | |_ ___ _ __ | |_ - | __| | | | '_ \| |/ / \___ \| | | | | | | | | |/ _ \ '_ \| __| - | | | | | | | | < ____) | |__| | |____ | |____| | | __/ | | | |_ - |_| |_|_|_| |_|_|\_\ |_____/ \___\_\______| \_____|_|_|\___|_| |_|\__| - - Welcome! Enter 'HELP;' to list all available commands. 'QUIT;' to exit. -``` - -6. Set the checkpointing interval to 3 seconds, and create corresponding tables with MySQL and Databend connectors in the Flink SQL Client. For the available connection parameters, see [https://github.com/databendcloud/flink-connector-databend#connector-options](https://github.com/databendcloud/flink-connector-databend#connector-options): - -```sql -Flink SQL> SET execution.checkpointing.interval = 3s; -[INFO] Session property has been set. - -Flink SQL> CREATE TABLE mysql_products (id INT,name STRING,description STRING,PRIMARY KEY (id) NOT ENFORCED) -WITH ('connector' = 'mysql-cdc', -'hostname' = 'localhost', -'port' = '3306', -'username' = 'root', -'password' = '123456', -'database-name' = 'mydb', -'table-name' = 'products', -'server-time-zone' = 'UTC' -); -[INFO] Execute statement succeed. - -Flink SQL> CREATE TABLE databend_products (id INT,name String,description String, PRIMARY KEY (`id`) NOT ENFORCED) -WITH ('connector' = 'databend', -'url'='databend://localhost:8000', -'username'='databend', -'password'='databend', -'database-name'='default', -'table-name'='products', -'sink.batch-size' = '5', -'sink.flush-interval' = '1000', -'sink.ignore-delete' = 'false', -'sink.max-retries' = '3'); -[INFO] Execute statement succeed. -``` - -7. In the Flink SQL Client, synchronize the data from the _mysql_products_ table to the _databend_products_ table: - -```sql -Flink SQL> INSERT INTO databend_products SELECT * FROM mysql_products; -[INFO] Submitting SQL update statement to the cluster... -[INFO] SQL update statement has been successfully submitted to the cluster: -Job ID: b14645f34937c7cf3672ffba35733734 -``` - -You can now see a running job in the Apache Flink Dashboard: - -![Alt text](/img/load/cdc-job.png) - -You're all set! If you query the _products_ table in Databend, you will see that the data from MySQL has been successfully synchronized. Feel free to perform insertions, updates, or deletions in MySQL, and you will observe the corresponding changes reflected in Databend as well. +- [Migrating from MySQL with Flink CDC](/tutorials/migrate/migrating-from-mysql-with-flink-cdc) \ No newline at end of file diff --git a/docs/en/tutorials/migrate/migrating-from-mysql-with-flink-cdc.md b/docs/en/tutorials/migrate/migrating-from-mysql-with-flink-cdc.md new file mode 100644 index 0000000000..59a673a387 --- /dev/null +++ b/docs/en/tutorials/migrate/migrating-from-mysql-with-flink-cdc.md @@ -0,0 +1,140 @@ +--- +title: Migrating from MySQL with Flink CDC +--- + +In this tutorial, you will set up a real-time data loading from MySQL to Databend with the Flink SQL connector for Databend. Before you start, make sure you have successfully set up Databend and MySQL in your environment. + +1. Create a table in MySQL and populate it with sample data. Then, create a corresponding target table in Databend. + +```sql title='In MySQL:' +CREATE DATABASE mydb; +USE mydb; + +CREATE TABLE products (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,description VARCHAR(512)); +ALTER TABLE products AUTO_INCREMENT = 10; + +INSERT INTO products VALUES (default,"scooter","Small 2-wheel scooter"), +(default,"car battery","12V car battery"), +(default,"12-pack drill bits","12-pack of drill bits with sizes ranging from #40 to #3"), +(default,"hammer","12oz carpenter's hammer"), +(default,"hammer","14oz carpenter's hammer"), +(default,"hammer","16oz carpenter's hammer"), +(default,"rocks","box of assorted rocks"), +(default,"jacket","black wind breaker"), +(default,"cloud","test for databend"), +(default,"spare tire","24 inch spare tire"); +``` + +```sql title='In Databend:' +CREATE TABLE products (id INT NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(512) ); +``` + +2. Download [Flink](https://flink.apache.org/downloads/) and the following SQL connectors to your system: + - Flink SQL connector for Databend: [https://github.com/databendcloud/flink-connector-databend/releases](https://github.com/databendcloud/flink-connector-databend/releases) + - Flink SQL connector for MySQL: [https://repo1.maven.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/2.3.0/flink-sql-connector-mysql-cdc-2.3.0.jar](https://repo1.maven.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/2.3.0/flink-sql-connector-mysql-cdc-2.3.0.jar) +3. Move the both connector JAR files to the _lib_ folder in your Flink installation directory. +4. Start Flink: + +```shell +cd flink-16.0 +./bin/start-cluster.sh +``` + +You can now open the Apache Flink Dashboard if you go to [http://localhost:8081](http://localhost:8081) in your browser: + +![Alt text](/img/load/cdc-dashboard.png) + +5. Start the Flink SQL Client: + +```shell +./bin/sql-client.sh + + ▒▓██▓██▒ + ▓████▒▒█▓▒▓███▓▒ + ▓███▓░░ ▒▒▒▓██▒ ▒ + ░██▒ ▒▒▓▓█▓▓▒░ ▒████ + ██▒ ░▒▓███▒ ▒█▒█▒ + ░▓█ ███ ▓░▒██ + ▓█ ▒▒▒▒▒▓██▓░▒░▓▓█ + █░ █ ▒▒░ ███▓▓█ ▒█▒▒▒ + ████░ ▒▓█▓ ██▒▒▒ ▓███▒ + ░▒█▓▓██ ▓█▒ ▓█▒▓██▓ ░█░ + ▓░▒▓████▒ ██ ▒█ █▓░▒█▒░▒█▒ + ███▓░██▓ ▓█ █ █▓ ▒▓█▓▓█▒ + ░██▓ ░█░ █ █▒ ▒█████▓▒ ██▓░▒ + ███░ ░ █░ ▓ ░█ █████▒░░ ░█░▓ ▓░ + ██▓█ ▒▒▓▒ ▓███████▓░ ▒█▒ ▒▓ ▓██▓ + ▒██▓ ▓█ █▓█ ░▒█████▓▓▒░ ██▒▒ █ ▒ ▓█▒ + ▓█▓ ▓█ ██▓ ░▓▓▓▓▓▓▓▒ ▒██▓ ░█▒ + ▓█ █ ▓███▓▒░ ░▓▓▓███▓ ░▒░ ▓█ + ██▓ ██▒ ░▒▓▓███▓▓▓▓▓██████▓▒ ▓███ █ + ▓███▒ ███ ░▓▓▒░░ ░▓████▓░ ░▒▓▒ █▓ + █▓▒▒▓▓██ ░▒▒░░░▒▒▒▒▓██▓░ █▓ + ██ ▓░▒█ ▓▓▓▓▒░░ ▒█▓ ▒▓▓██▓ ▓▒ ▒▒▓ + ▓█▓ ▓▒█ █▓░ ░▒▓▓██▒ ░▓█▒ ▒▒▒░▒▒▓█████▒ + ██░ ▓█▒█▒ ▒▓▓▒ ▓█ █░ ░░░░ ░█▒ + ▓█ ▒█▓ ░ █░ ▒█ █▓ + █▓ ██ █░ ▓▓ ▒█▓▓▓▒█░ + █▓ ░▓██░ ▓▒ ▓█▓▒░░░▒▓█░ ▒█ + ██ ▓█▓░ ▒ ░▒█▒██▒ ▓▓ + ▓█▒ ▒█▓▒░ ▒▒ █▒█▓▒▒░░▒██ + ░██▒ ▒▓▓▒ ▓██▓▒█▒ ░▓▓▓▓▒█▓ + ░▓██▒ ▓░ ▒█▓█ ░░▒▒▒ + ▒▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░▓▓ ▓░▒█░ + + ______ _ _ _ _____ ____ _ _____ _ _ _ BETA + | ____| (_) | | / ____|/ __ \| | / ____| (_) | | + | |__ | |_ _ __ | | __ | (___ | | | | | | | | |_ ___ _ __ | |_ + | __| | | | '_ \| |/ / \___ \| | | | | | | | | |/ _ \ '_ \| __| + | | | | | | | | < ____) | |__| | |____ | |____| | | __/ | | | |_ + |_| |_|_|_| |_|_|\_\ |_____/ \___\_\______| \_____|_|_|\___|_| |_|\__| + + Welcome! Enter 'HELP;' to list all available commands. 'QUIT;' to exit. +``` + +6. Set the checkpointing interval to 3 seconds, and create corresponding tables with MySQL and Databend connectors in the Flink SQL Client. For the available connection parameters, see [https://github.com/databendcloud/flink-connector-databend#connector-options](https://github.com/databendcloud/flink-connector-databend#connector-options): + +```sql +Flink SQL> SET execution.checkpointing.interval = 3s; +[INFO] Session property has been set. + +Flink SQL> CREATE TABLE mysql_products (id INT,name STRING,description STRING,PRIMARY KEY (id) NOT ENFORCED) +WITH ('connector' = 'mysql-cdc', +'hostname' = 'localhost', +'port' = '3306', +'username' = 'root', +'password' = '123456', +'database-name' = 'mydb', +'table-name' = 'products', +'server-time-zone' = 'UTC' +); +[INFO] Execute statement succeed. + +Flink SQL> CREATE TABLE databend_products (id INT,name String,description String, PRIMARY KEY (`id`) NOT ENFORCED) +WITH ('connector' = 'databend', +'url'='databend://localhost:8000', +'username'='databend', +'password'='databend', +'database-name'='default', +'table-name'='products', +'sink.batch-size' = '5', +'sink.flush-interval' = '1000', +'sink.ignore-delete' = 'false', +'sink.max-retries' = '3'); +[INFO] Execute statement succeed. +``` + +7. In the Flink SQL Client, synchronize the data from the _mysql_products_ table to the _databend_products_ table: + +```sql +Flink SQL> INSERT INTO databend_products SELECT * FROM mysql_products; +[INFO] Submitting SQL update statement to the cluster... +[INFO] SQL update statement has been successfully submitted to the cluster: +Job ID: b14645f34937c7cf3672ffba35733734 +``` + +You can now see a running job in the Apache Flink Dashboard: + +![Alt text](/img/load/cdc-job.png) + +You're all set! If you query the _products_ table in Databend, you will see that the data from MySQL has been successfully synchronized. Feel free to perform insertions, updates, or deletions in MySQL, and you will observe the corresponding changes reflected in Databend as well. \ No newline at end of file From ada351c3a6b129ae9efd336014e7eb3166302cdc Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Tue, 14 Jan 2025 22:44:33 -0500 Subject: [PATCH 06/10] updates --- .../guides/40-load-data/02-load-db/addax.md | 24 --- .../guides/40-load-data/02-load-db/datax.md | 29 ---- .../40-load-data/02-load-db/debezium.md | 94 ----------- .../40-load-data/02-load-db/flink-cdc.md | 31 ---- .../guides/40-load-data/02-load-db/index.md | 4 - docs/en/guides/41-migrate/_category_.json | 3 + docs/en/guides/41-migrate/index.md | 8 + docs/en/guides/41-migrate/mysql.md | 157 ++++++++++++++++++ 8 files changed, 168 insertions(+), 182 deletions(-) delete mode 100644 docs/en/guides/40-load-data/02-load-db/addax.md delete mode 100644 docs/en/guides/40-load-data/02-load-db/datax.md delete mode 100644 docs/en/guides/40-load-data/02-load-db/debezium.md delete mode 100644 docs/en/guides/40-load-data/02-load-db/flink-cdc.md create mode 100644 docs/en/guides/41-migrate/_category_.json create mode 100644 docs/en/guides/41-migrate/index.md create mode 100644 docs/en/guides/41-migrate/mysql.md diff --git a/docs/en/guides/40-load-data/02-load-db/addax.md b/docs/en/guides/40-load-data/02-load-db/addax.md deleted file mode 100644 index 2bf8c2c8b0..0000000000 --- a/docs/en/guides/40-load-data/02-load-db/addax.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Addax ---- - -import FunctionDescription from '@site/src/components/FunctionDescription'; - - - -[Addax](https://github.com/wgzhao/Addax), originally derived from Alibaba's [DataX](https://github.com/alibaba/DataX), is a versatile open-source ETL (Extract, Transform, Load) tool. It excels at seamlessly transferring data between diverse RDBMS (Relational Database Management Systems) and NoSQL databases, making it an optimal solution for efficient data migration. - -For information about the system requirements, download, and deployment steps for Addax, refer to Addax's [Getting Started Guide](https://github.com/wgzhao/Addax#getting-started). The guide provides detailed instructions and guidelines for setting up and using Addax. - -See also: [DataX](datax.md) - -## DatabendReader & DatabendWriter - -DatabendReader and DatabendWriter are integrated plugins of Addax, allowing seamless integration with Databend. - -The DatabendReader plugin enables reading data from Databend. Databend provides compatibility with the MySQL client protocol, so you can also use the [MySQLReader](https://wgzhao.github.io/Addax/develop/reader/mysqlreader/) plugin to retrieve data from Databend. For more information about DatabendReader, see https://wgzhao.github.io/Addax/develop/reader/databendreader/ - -## Tutorials - -- [Migrating from MySQL with Addax](/tutorials/migrate/migrating-from-mysql-with-addax) - diff --git a/docs/en/guides/40-load-data/02-load-db/datax.md b/docs/en/guides/40-load-data/02-load-db/datax.md deleted file mode 100644 index 7d1b0fb7a8..0000000000 --- a/docs/en/guides/40-load-data/02-load-db/datax.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: DataX ---- - -import FunctionDescription from '@site/src/components/FunctionDescription'; - - - -[DataX](https://github.com/alibaba/DataX) is an open-source data integration tool developed by Alibaba. It is designed to efficiently and reliably transfer data between various data storage systems and platforms, such as relational databases, big data platforms, and cloud storage services. DataX supports a wide range of data sources and data sinks, including but not limited to MySQL, Oracle, SQL Server, PostgreSQL, HDFS, Hive, HBase, MongoDB, and more. - -:::tip -[Apache DolphinScheduler](https://dolphinscheduler.apache.org/) now has added support for Databend as a data source. This enhancement enables you to leverage DolphinScheduler for managing DataX tasks and effortlessly load data from MySQL to Databend. -::: - -For information about the system requirements, download, and deployment steps for DataX, refer to DataX's [Quick Start Guide](https://github.com/alibaba/DataX/blob/master/userGuid.md). The guide provides detailed instructions and guidelines for setting up and using DataX. - -See also: [Addax](addax.md) - -## DatabendWriter - -DatabendWriter is an integrated plugin of DataX, which means it comes pre-installed and does not require any manual installation. It acts as a seamless connector that enables the effortless transfer of data from other databases to Databend. With DatabendWriter, you can leverage the capabilities of DataX to efficiently load data from various databases into Databend. - -DatabendWriter supports two operational modes: INSERT (default) and REPLACE. In INSERT Mode, new data is added while conflicts with existing records are prevented to maintain data integrity. On the other hand, the REPLACE Mode prioritizes data consistency by replacing existing records with newer data in case of conflicts. - -If you need more information about DatabendWriter and its functionalities, you can refer to the documentation available at https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md - -## Tutorials - -- [Migrating from MySQL with DataX](/tutorials/migrate/migrating-from-mysql-with-datax) \ No newline at end of file diff --git a/docs/en/guides/40-load-data/02-load-db/debezium.md b/docs/en/guides/40-load-data/02-load-db/debezium.md deleted file mode 100644 index ee5865819d..0000000000 --- a/docs/en/guides/40-load-data/02-load-db/debezium.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Debezium ---- - -[Debezium](https://debezium.io/) is a set of distributed services to capture changes in your databases so that your applications can see those changes and respond to them. Debezium records all row-level changes within each database table in a change event stream, and applications simply read these streams to see the change events in the same order in which they occurred. - -[debezium-server-databend](https://github.com/databendcloud/debezium-server-databend) is a lightweight CDC tool developed by Databend, based on Debezium Engine. Its purpose is to capture real-time changes in relational databases and deliver them as event streams to ultimately write the data into the target database Databend. This tool provides a simple way to monitor and capture database changes, transforming them into consumable events without the need for large data infrastructures like Flink, Kafka, or Spark. - -## Installing debezium-server-databend - -debezium-server-databend can be installed independently without the need for installing Debezium beforehand. Once you have decided to install debezium-server-databend, you have two options available. The first one is to install it from source by downloading the source code and building it yourself. Alternatively, you can opt for a more straightforward installation process using Docker. - -### Installing from Source - -Before you start, make sure JDK 11 and Maven are installed on your system. - -1. Clone the project: - -```bash -git clone https://github.com/databendcloud/debezium-server-databend.git -``` - -2. Change into the project's root directory: - -```bash -cd debezium-server-databend -``` - -3. Build and package debezium server: - -```go -mvn -Passembly -Dmaven.test.skip package -``` - -4. Once the build is completed, unzip the server distribution package: - -```bash -unzip debezium-server-databend-dist/target/debezium-server-databend-dist*.zip -d databendDist -``` - -5. Enter the extracted folder: - -```bash -cd databendDist -``` - -6. Create a file named _application.properties_ in the _conf_ folder with the content in the sample [here](https://github.com/databendcloud/debezium-server-databend/blob/main/debezium-server-databend-dist/src/main/resources/distro/conf/application.properties.example), and modify the configurations according to your specific requirements. For description of the available parameters, see this [page](https://github.com/databendcloud/debezium-server-databend/blob/main/docs/docs.md). - -```bash -nano conf/application.properties -``` - -7. Use the provided script to start the tool: - -```bash -bash run.sh -``` - -### Installing with Docker - -Before you start, make sure Docker and Docker Compose are installed on your system. - -1. Create a file named _application.properties_ in the _conf_ folder with the content in the sample [here](https://github.com/databendcloud/debezium-server-databend/blob/main/debezium-server-databend-dist/src/main/resources/distro/conf/application.properties.example), and modify the configurations according to your specific requirements. For description of the available Databend parameters, see this [page](https://github.com/databendcloud/debezium-server-databend/blob/main/docs/docs.md). - -```bash -nano conf/application.properties -``` - -2. Create a file named _docker-compose.yml_ with the following content: - -```dockerfile -version: '2.1' -services: - debezium: - image: ghcr.io/databendcloud/debezium-server-databend:pr-2 - ports: - - "8080:8080" - - "8083:8083" - volumes: - - $PWD/conf:/app/conf - - $PWD/data:/app/data -``` - -3. Open a terminal or command-line interface and navigate to the directory containing the _docker-compose.yml_ file. - -4. Use the following command to start the tool: - -```bash -docker-compose up -d -``` - -## Tutorials - -- [Migrating from MySQL with Debezium](/tutorials/migrate/migrating-from-mysql-with-debezium) \ No newline at end of file diff --git a/docs/en/guides/40-load-data/02-load-db/flink-cdc.md b/docs/en/guides/40-load-data/02-load-db/flink-cdc.md deleted file mode 100644 index 6c8a632e0e..0000000000 --- a/docs/en/guides/40-load-data/02-load-db/flink-cdc.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Flink CDC ---- - -import FunctionDescription from '@site/src/components/FunctionDescription'; - - - -[Apache Flink](https://github.com/apache/flink) CDC (Change Data Capture) refers to the capability of Apache Flink to capture and process real-time data changes from various sources using SQL-based queries. CDC allows you to monitor and capture data modifications (inserts, updates, and deletes) happening in a database or streaming system and react to those changes in real time. You can utilize the [Flink SQL connector for Databend](https://github.com/databendcloud/flink-connector-databend) to load data from other databases in real-time into Databend. The Flink SQL connector for Databend offers a connector that integrates Flink's stream processing capabilities with Databend. By configuring this connector, you can capture data changes from various databases as streams and load them into Databend for processing and analysis in real-time. - -## Downloading & Installing Connector - -To download and install the Flink SQL connector for Databend, follow these steps: - -1. Download and set up Flink: Before installing the Flink SQL connector for Databend, ensure that you have downloaded and set up Flink on your system. You can download Flink from the official website: https://flink.apache.org/downloads/ - -2. Download the connector: Visit the releases page of the Flink SQL connector for Databend on GitHub: [https://github.com/databendcloud/flink-connector-databend/releases](https://github.com/databendcloud/flink-connector-databend/releases). Download the latest version of the connector (e.g., flink-connector-databend-0.0.2.jar). - - Please note that you can also compile the Flink SQL connector for Databend from source: - - ```shell - git clone https://github.com/databendcloud/flink-connector-databend - cd flink-connector-databend - mvn clean install -DskipTests - ``` - -3. Move the JAR file: Once you have downloaded the connector, move the JAR file to the lib folder in your Flink installation directory. For example, if you have Flink version 1.16.0 installed, move the JAR file to the flink-1.16.0/lib/ directory. - -## Tutorials - -- [Migrating from MySQL with Flink CDC](/tutorials/migrate/migrating-from-mysql-with-flink-cdc) \ No newline at end of file diff --git a/docs/en/guides/40-load-data/02-load-db/index.md b/docs/en/guides/40-load-data/02-load-db/index.md index 49e70e1fe1..fe8ed1f623 100644 --- a/docs/en/guides/40-load-data/02-load-db/index.md +++ b/docs/en/guides/40-load-data/02-load-db/index.md @@ -10,11 +10,7 @@ These connectors also support Databend Cloud. For setup instructions, visit: [Co | Tool | Plugin / Connector | |----------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Addax | [DatabendReader](https://wgzhao.github.io/Addax/develop/reader/databendreader/) & [DatabendWriter](https://wgzhao.github.io/Addax/develop/writer/databendwriter/) | | Airbyte | [datafuselabs/destination-databend:alpha](https://hub.docker.com/r/airbyte/destination-databend) | -| DataX | [DatabendWriter](https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md) | | dbt | [dbt-databend-cloud](https://github.com/databendcloud/dbt-databend) | -| Debezium | [debezium-server-databend](https://github.com/databendcloud/debezium-server-databend) | -| Flink CDC | [Flink SQL connector for Databend](https://github.com/databendcloud/flink-connector-databend) | | Kafka | [bend-ingest-kafka](https://github.com/databendcloud/bend-ingest-kafka) | | Vector | [Databend sink](https://vector.dev/docs/reference/configuration/sinks/databend/) | diff --git a/docs/en/guides/41-migrate/_category_.json b/docs/en/guides/41-migrate/_category_.json new file mode 100644 index 0000000000..5224f7ca97 --- /dev/null +++ b/docs/en/guides/41-migrate/_category_.json @@ -0,0 +1,3 @@ +{ + "label": "Migrating from Databases" +} \ No newline at end of file diff --git a/docs/en/guides/41-migrate/index.md b/docs/en/guides/41-migrate/index.md new file mode 100644 index 0000000000..417ef5d612 --- /dev/null +++ b/docs/en/guides/41-migrate/index.md @@ -0,0 +1,8 @@ +--- +title: Migrating from Databases +--- +import IndexOverviewList from '@site/src/components/IndexOverviewList'; + +This guide introduces how to migrate your data from different databases to Databend: + + \ No newline at end of file diff --git a/docs/en/guides/41-migrate/mysql.md b/docs/en/guides/41-migrate/mysql.md new file mode 100644 index 0000000000..63dfb7595b --- /dev/null +++ b/docs/en/guides/41-migrate/mysql.md @@ -0,0 +1,157 @@ +--- +title: MySQL +--- + +This guide explains how to migrate data from MySQL to Databend. Databend supports two main migration approaches: batch loading and continuous data synchronization. + +## Batch Loading + +To migrate data from MySQL to Databend in batches, you can utilize tools such as Addax or DataX. + +### Addax + +[Addax](https://github.com/wgzhao/Addax), originally derived from Alibaba's [DataX](https://github.com/alibaba/DataX), is a versatile open-source ETL (Extract, Transform, Load) tool. It excels at seamlessly transferring data between diverse RDBMS (Relational Database Management Systems) and NoSQL databases, making it an optimal solution for efficient data migration. + +For information about the system requirements, download, and deployment steps for Addax, refer to Addax's [Getting Started Guide](https://github.com/wgzhao/Addax#getting-started). The guide provides detailed instructions and guidelines for setting up and using Addax. + +#### DatabendReader & DatabendWriter + +DatabendReader and DatabendWriter are integrated plugins of Addax, allowing seamless integration with Databend. The DatabendReader plugin enables reading data from Databend. Databend provides compatibility with the MySQL client protocol, so you can also use the [MySQLReader](https://wgzhao.github.io/Addax/develop/reader/mysqlreader/) plugin to retrieve data from Databend. For more information about DatabendReader, see https://wgzhao.github.io/Addax/develop/reader/databendreader/ + +### DataX + +[DataX](https://github.com/alibaba/DataX) is an open-source data integration tool developed by Alibaba. It is designed to efficiently and reliably transfer data between various data storage systems and platforms, such as relational databases, big data platforms, and cloud storage services. DataX supports a wide range of data sources and data sinks, including but not limited to MySQL, Oracle, SQL Server, PostgreSQL, HDFS, Hive, HBase, MongoDB, and more. + +:::tip +[Apache DolphinScheduler](https://dolphinscheduler.apache.org/) now has added support for Databend as a data source. This enhancement enables you to leverage DolphinScheduler for managing DataX tasks and effortlessly load data from MySQL to Databend. +::: + +For information about the system requirements, download, and deployment steps for DataX, refer to DataX's [Quick Start Guide](https://github.com/alibaba/DataX/blob/master/userGuid.md). The guide provides detailed instructions and guidelines for setting up and using DataX. + +#### DatabendWriter + +DatabendWriter is an integrated plugin of DataX, which means it comes pre-installed and does not require any manual installation. It acts as a seamless connector that enables the effortless transfer of data from other databases to Databend. With DatabendWriter, you can leverage the capabilities of DataX to efficiently load data from various databases into Databend. + +DatabendWriter supports two operational modes: INSERT (default) and REPLACE. In INSERT Mode, new data is added while conflicts with existing records are prevented to maintain data integrity. On the other hand, the REPLACE Mode prioritizes data consistency by replacing existing records with newer data in case of conflicts. + +If you need more information about DatabendWriter and its functionalities, you can refer to the documentation available at https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md + +## Continuous Synchronization with CDC + +To migrate data from MySQL to Databend in real-time, you can use Change Data Capture (CDC) tools such as Debezium or Flink CDC. + +### Debezium + +[Debezium](https://debezium.io/) is a set of distributed services to capture changes in your databases so that your applications can see those changes and respond to them. Debezium records all row-level changes within each database table in a change event stream, and applications simply read these streams to see the change events in the same order in which they occurred. + +[debezium-server-databend](https://github.com/databendcloud/debezium-server-databend) is a lightweight CDC tool developed by Databend, based on Debezium Engine. Its purpose is to capture real-time changes in relational databases and deliver them as event streams to ultimately write the data into the target database Databend. This tool provides a simple way to monitor and capture database changes, transforming them into consumable events without the need for large data infrastructures like Flink, Kafka, or Spark. + +debezium-server-databend can be installed independently without the need for installing Debezium beforehand. Once you have decided to install debezium-server-databend, you have two options available. The first one is to install it from source by downloading the source code and building it yourself. Alternatively, you can opt for a more straightforward installation process using Docker. + +#### Installing debezium-server-databend from Source + +Before you start, make sure JDK 11 and Maven are installed on your system. + +1. Clone the project: + +```bash +git clone https://github.com/databendcloud/debezium-server-databend.git +``` + +2. Change into the project's root directory: + +```bash +cd debezium-server-databend +``` + +3. Build and package debezium server: + +```go +mvn -Passembly -Dmaven.test.skip package +``` + +4. Once the build is completed, unzip the server distribution package: + +```bash +unzip debezium-server-databend-dist/target/debezium-server-databend-dist*.zip -d databendDist +``` + +5. Enter the extracted folder: + +```bash +cd databendDist +``` + +6. Create a file named _application.properties_ in the _conf_ folder with the content in the sample [here](https://github.com/databendcloud/debezium-server-databend/blob/main/debezium-server-databend-dist/src/main/resources/distro/conf/application.properties.example), and modify the configurations according to your specific requirements. For description of the available parameters, see this [page](https://github.com/databendcloud/debezium-server-databend/blob/main/docs/docs.md). + +```bash +nano conf/application.properties +``` + +7. Use the provided script to start the tool: + +```bash +bash run.sh +``` + +#### Installing debezium-server-databend with Docker + +Before you start, make sure Docker and Docker Compose are installed on your system. + +1. Create a file named _application.properties_ in the _conf_ folder with the content in the sample [here](https://github.com/databendcloud/debezium-server-databend/blob/main/debezium-server-databend-dist/src/main/resources/distro/conf/application.properties.example), and modify the configurations according to your specific requirements. For description of the available Databend parameters, see this [page](https://github.com/databendcloud/debezium-server-databend/blob/main/docs/docs.md). + +```bash +nano conf/application.properties +``` + +2. Create a file named _docker-compose.yml_ with the following content: + +```dockerfile +version: '2.1' +services: + debezium: + image: ghcr.io/databendcloud/debezium-server-databend:pr-2 + ports: + - "8080:8080" + - "8083:8083" + volumes: + - $PWD/conf:/app/conf + - $PWD/data:/app/data +``` + +3. Open a terminal or command-line interface and navigate to the directory containing the _docker-compose.yml_ file. + +4. Use the following command to start the tool: + +```bash +docker-compose up -d +``` + +### Flink CDC + +[Apache Flink](https://github.com/apache/flink) CDC (Change Data Capture) refers to the capability of Apache Flink to capture and process real-time data changes from various sources using SQL-based queries. CDC allows you to monitor and capture data modifications (inserts, updates, and deletes) happening in a database or streaming system and react to those changes in real time. You can utilize the [Flink SQL connector for Databend](https://github.com/databendcloud/flink-connector-databend) to load data from other databases in real-time into Databend. The Flink SQL connector for Databend offers a connector that integrates Flink's stream processing capabilities with Databend. By configuring this connector, you can capture data changes from various databases as streams and load them into Databend for processing and analysis in real-time. + +#### Downloading & Installing Connector + +To download and install the Flink SQL connector for Databend, follow these steps: + +1. Download and set up Flink: Before installing the Flink SQL connector for Databend, ensure that you have downloaded and set up Flink on your system. You can download Flink from the official website: https://flink.apache.org/downloads/ + +2. Download the connector: Visit the releases page of the Flink SQL connector for Databend on GitHub: [https://github.com/databendcloud/flink-connector-databend/releases](https://github.com/databendcloud/flink-connector-databend/releases). Download the latest version of the connector (e.g., flink-connector-databend-0.0.2.jar). + + Please note that you can also compile the Flink SQL connector for Databend from source: + + ```shell + git clone https://github.com/databendcloud/flink-connector-databend + cd flink-connector-databend + mvn clean install -DskipTests + ``` + +3. Move the JAR file: Once you have downloaded the connector, move the JAR file to the lib folder in your Flink installation directory. For example, if you have Flink version 1.16.0 installed, move the JAR file to the flink-1.16.0/lib/ directory. + +## Tutorials + +- [Migrating from MySQL with Addax](/tutorials/migrate/migrating-from-mysql-with-addax) +- [Migrating from MySQL with DataX](/tutorials/migrate/migrating-from-mysql-with-datax) +- [Migrating from MySQL with Debezium](/tutorials/migrate/migrating-from-mysql-with-debezium) +- [Migrating from MySQL with Flink CDC](/tutorials/migrate/migrating-from-mysql-with-flink-cdc) \ No newline at end of file From 3ef9cc352d6e07502b2c3bfe59287b99e0acf8d2 Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Wed, 15 Jan 2025 14:54:06 -0500 Subject: [PATCH 07/10] update titles --- .../guides/40-load-data/01-load/_category_.json | 2 +- docs/en/guides/40-load-data/01-load/index.md | 2 +- .../40-load-data/02-load-db/_category_.json | 2 +- docs/en/guides/40-load-data/02-load-db/index.md | 15 ++++----------- .../03-load-semistructured/_category_.json | 2 +- .../40-load-data/03-load-semistructured/index.md | 2 +- 6 files changed, 9 insertions(+), 16 deletions(-) diff --git a/docs/en/guides/40-load-data/01-load/_category_.json b/docs/en/guides/40-load-data/01-load/_category_.json index 4f8a45e91e..7f11eae549 100644 --- a/docs/en/guides/40-load-data/01-load/_category_.json +++ b/docs/en/guides/40-load-data/01-load/_category_.json @@ -1,3 +1,3 @@ { - "label": "Loading Data from Files" + "label": "Loading from Files" } \ No newline at end of file diff --git a/docs/en/guides/40-load-data/01-load/index.md b/docs/en/guides/40-load-data/01-load/index.md index 2f07d7d1b3..d6a3a1898e 100644 --- a/docs/en/guides/40-load-data/01-load/index.md +++ b/docs/en/guides/40-load-data/01-load/index.md @@ -1,5 +1,5 @@ --- -title: Loading Data from Files +title: Loading from Files --- import DetailsWrap from '@site/src/components/DetailsWrap'; diff --git a/docs/en/guides/40-load-data/02-load-db/_category_.json b/docs/en/guides/40-load-data/02-load-db/_category_.json index 2a128497ea..1e231c9ce2 100644 --- a/docs/en/guides/40-load-data/02-load-db/_category_.json +++ b/docs/en/guides/40-load-data/02-load-db/_category_.json @@ -1,3 +1,3 @@ { - "label": "Loading Data with Tools" + "label": "Loading with Platforms" } \ No newline at end of file diff --git a/docs/en/guides/40-load-data/02-load-db/index.md b/docs/en/guides/40-load-data/02-load-db/index.md index fe8ed1f623..0389638284 100644 --- a/docs/en/guides/40-load-data/02-load-db/index.md +++ b/docs/en/guides/40-load-data/02-load-db/index.md @@ -1,16 +1,9 @@ --- -title: Loading Data with Tools +title: Loading with Platforms --- -Databend offers connectors and plugins for integrating with major data import tools, ensuring efficient data synchronization. See the below table for supported tools and their Databend connectors. +import IndexOverviewList from '@site/src/components/IndexOverviewList'; -:::info -These connectors also support Databend Cloud. For setup instructions, visit: [Connecting to a Warehouse](/guides/cloud/using-databend-cloud/warehouses/#connecting) -::: +This guide introduces platforms for loading data into Databend, including: -| Tool | Plugin / Connector | -|----------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Airbyte | [datafuselabs/destination-databend:alpha](https://hub.docker.com/r/airbyte/destination-databend) | -| dbt | [dbt-databend-cloud](https://github.com/databendcloud/dbt-databend) | -| Kafka | [bend-ingest-kafka](https://github.com/databendcloud/bend-ingest-kafka) | -| Vector | [Databend sink](https://vector.dev/docs/reference/configuration/sinks/databend/) | + diff --git a/docs/en/guides/40-load-data/03-load-semistructured/_category_.json b/docs/en/guides/40-load-data/03-load-semistructured/_category_.json index e277154890..de293952c4 100644 --- a/docs/en/guides/40-load-data/03-load-semistructured/_category_.json +++ b/docs/en/guides/40-load-data/03-load-semistructured/_category_.json @@ -1,3 +1,3 @@ { - "label": "Loading Semi-structured Data" + "label": "Loading Semi-structured Formats" } \ No newline at end of file diff --git a/docs/en/guides/40-load-data/03-load-semistructured/index.md b/docs/en/guides/40-load-data/03-load-semistructured/index.md index 468b01c0fe..dfd533a159 100644 --- a/docs/en/guides/40-load-data/03-load-semistructured/index.md +++ b/docs/en/guides/40-load-data/03-load-semistructured/index.md @@ -1,5 +1,5 @@ --- -title: Loading Semi-structured Data +title: Loading Semi-structured Formats --- import IndexOverviewList from '@site/src/components/IndexOverviewList'; From d0fdef46a6dda72c7cfa819af9e1ce1946589b80 Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Wed, 15 Jan 2025 15:07:54 -0500 Subject: [PATCH 08/10] update titles --- docs/en/guides/40-load-data/01-load/00-stage.md | 1 + docs/en/guides/40-load-data/01-load/01-s3.md | 1 + docs/en/guides/40-load-data/01-load/02-local.md | 1 + docs/en/guides/40-load-data/01-load/03-http.md | 1 + docs/en/guides/40-load-data/01-load/_category_.json | 2 +- .../40-load-data/03-load-semistructured/00-load-parquet.md | 2 +- .../guides/40-load-data/03-load-semistructured/01-load-csv.md | 2 +- .../guides/40-load-data/03-load-semistructured/02-load-tsv.md | 2 +- .../40-load-data/03-load-semistructured/03-load-ndjson.md | 2 +- .../guides/40-load-data/03-load-semistructured/04-load-orc.md | 2 +- docs/en/guides/40-load-data/04-transform/00-querying-parquet.md | 2 +- docs/en/guides/40-load-data/04-transform/01-querying-csv.md | 2 +- docs/en/guides/40-load-data/04-transform/02-querying-tsv.md | 2 +- docs/en/guides/40-load-data/04-transform/03-querying-ndjson.md | 2 +- docs/en/guides/40-load-data/04-transform/03-querying-orc.md | 2 +- .../en/guides/40-load-data/04-transform/04-querying-metadata.md | 2 +- 16 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/en/guides/40-load-data/01-load/00-stage.md b/docs/en/guides/40-load-data/01-load/00-stage.md index eaf2416883..d836d0829d 100644 --- a/docs/en/guides/40-load-data/01-load/00-stage.md +++ b/docs/en/guides/40-load-data/01-load/00-stage.md @@ -1,5 +1,6 @@ --- title: Loading from Stage +sidebar_label: Stage --- Databend enables you to easily import data from files uploaded to either the user stage or an internal/external stage. To do so, you can first upload the files to a stage using [BendSQL](../../30-sql-clients/00-bendsql/index.md), and then employ the [COPY INTO](/sql/sql-commands/dml/dml-copy-into-table) command to load the data from the staged file. Please note that the files must be in a format supported by Databend, otherwise the data cannot be imported. For more information on the file formats supported by Databend, see [Input & Output File Formats](/sql/sql-reference/file-format-options). diff --git a/docs/en/guides/40-load-data/01-load/01-s3.md b/docs/en/guides/40-load-data/01-load/01-s3.md index a3fcddecae..21cd16615a 100644 --- a/docs/en/guides/40-load-data/01-load/01-s3.md +++ b/docs/en/guides/40-load-data/01-load/01-s3.md @@ -1,5 +1,6 @@ --- title: Loading from Bucket +sidebar_label: Bucket --- When data files are stored in an object storage bucket, such as Amazon S3, it is possible to load them directly into Databend using the [COPY INTO](/sql/sql-commands/dml/dml-copy-into-table) command. Please note that the files must be in a format supported by Databend, otherwise the data cannot be imported. For more information on the file formats supported by Databend, see [Input & Output File Formats](/sql/sql-reference/file-format-options). diff --git a/docs/en/guides/40-load-data/01-load/02-local.md b/docs/en/guides/40-load-data/01-load/02-local.md index 44ed1322e4..98e5f04ecf 100644 --- a/docs/en/guides/40-load-data/01-load/02-local.md +++ b/docs/en/guides/40-load-data/01-load/02-local.md @@ -1,5 +1,6 @@ --- title: Loading from Local File +sidebar_label: Local --- Uploading your local data files to a stage or bucket before loading them into Databend can be unnecessary. Instead, you can use [BendSQL](../../30-sql-clients/00-bendsql/index.md), the Databend native CLI tool, to directly import the data. This simplifies the workflow and can save you storage fees. diff --git a/docs/en/guides/40-load-data/01-load/03-http.md b/docs/en/guides/40-load-data/01-load/03-http.md index 212f6c05ca..631cdc0f49 100644 --- a/docs/en/guides/40-load-data/01-load/03-http.md +++ b/docs/en/guides/40-load-data/01-load/03-http.md @@ -1,5 +1,6 @@ --- title: Loading from Remote File +sidebar_label: Remote --- To load data from remote files into Databend, the [COPY INTO](/sql/sql-commands/dml/dml-copy-into-table) command can be used. This command allows you to copy data from a variety of sources, including remote files, into Databend with ease. With COPY INTO, you can specify the source file location, file format, and other relevant parameters to tailor the import process to your needs. Please note that the files must be in a format supported by Databend, otherwise the data cannot be imported. For more information on the file formats supported by Databend, see [Input & Output File Formats](/sql/sql-reference/file-format-options). diff --git a/docs/en/guides/40-load-data/01-load/_category_.json b/docs/en/guides/40-load-data/01-load/_category_.json index 7f11eae549..b2419053e4 100644 --- a/docs/en/guides/40-load-data/01-load/_category_.json +++ b/docs/en/guides/40-load-data/01-load/_category_.json @@ -1,3 +1,3 @@ { - "label": "Loading from Files" + "label": "Loading Files" } \ No newline at end of file diff --git a/docs/en/guides/40-load-data/03-load-semistructured/00-load-parquet.md b/docs/en/guides/40-load-data/03-load-semistructured/00-load-parquet.md index 550bdefb9f..2699c1376d 100644 --- a/docs/en/guides/40-load-data/03-load-semistructured/00-load-parquet.md +++ b/docs/en/guides/40-load-data/03-load-semistructured/00-load-parquet.md @@ -1,6 +1,6 @@ --- title: Loading Parquet File into Databend -sidebar_label: Loading Parquet File +sidebar_label: Parquet --- ## What is Parquet? diff --git a/docs/en/guides/40-load-data/03-load-semistructured/01-load-csv.md b/docs/en/guides/40-load-data/03-load-semistructured/01-load-csv.md index e0558d39fd..03d84981ad 100644 --- a/docs/en/guides/40-load-data/03-load-semistructured/01-load-csv.md +++ b/docs/en/guides/40-load-data/03-load-semistructured/01-load-csv.md @@ -1,6 +1,6 @@ --- title: Loading CSV File into Databend -sidebar_label: Loading CSV File +sidebar_label: CSV --- ## What is CSV? diff --git a/docs/en/guides/40-load-data/03-load-semistructured/02-load-tsv.md b/docs/en/guides/40-load-data/03-load-semistructured/02-load-tsv.md index 321b6fb893..2e4631854c 100644 --- a/docs/en/guides/40-load-data/03-load-semistructured/02-load-tsv.md +++ b/docs/en/guides/40-load-data/03-load-semistructured/02-load-tsv.md @@ -1,6 +1,6 @@ --- title: Loading TSV File into Databend -sidebar_label: Loading TSV File +sidebar_label: TSV --- ## What is TSV? diff --git a/docs/en/guides/40-load-data/03-load-semistructured/03-load-ndjson.md b/docs/en/guides/40-load-data/03-load-semistructured/03-load-ndjson.md index a274e9dee5..d7361a9b5b 100644 --- a/docs/en/guides/40-load-data/03-load-semistructured/03-load-ndjson.md +++ b/docs/en/guides/40-load-data/03-load-semistructured/03-load-ndjson.md @@ -1,6 +1,6 @@ --- title: Loading NDJSON File into Databend -sidebar_label: Loading NDJSON File +sidebar_label: NDJSON --- ## What is NDJSON? diff --git a/docs/en/guides/40-load-data/03-load-semistructured/04-load-orc.md b/docs/en/guides/40-load-data/03-load-semistructured/04-load-orc.md index af39095319..7a196a0ff0 100644 --- a/docs/en/guides/40-load-data/03-load-semistructured/04-load-orc.md +++ b/docs/en/guides/40-load-data/03-load-semistructured/04-load-orc.md @@ -1,6 +1,6 @@ --- title: Loading ORC File into Databend -sidebar_label: Loading ORC File +sidebar_label: ORC --- ## What is ORC? diff --git a/docs/en/guides/40-load-data/04-transform/00-querying-parquet.md b/docs/en/guides/40-load-data/04-transform/00-querying-parquet.md index 56a355ac61..4182665693 100644 --- a/docs/en/guides/40-load-data/04-transform/00-querying-parquet.md +++ b/docs/en/guides/40-load-data/04-transform/00-querying-parquet.md @@ -1,6 +1,6 @@ --- title: Querying Parquet Files in Stage -sidebar_label: Querying Parquet File +sidebar_label: Parquet --- ## Query Parquet Files in Stage diff --git a/docs/en/guides/40-load-data/04-transform/01-querying-csv.md b/docs/en/guides/40-load-data/04-transform/01-querying-csv.md index 1141beb8a5..23a6bb0db5 100644 --- a/docs/en/guides/40-load-data/04-transform/01-querying-csv.md +++ b/docs/en/guides/40-load-data/04-transform/01-querying-csv.md @@ -1,6 +1,6 @@ --- title: Querying CSV Files in Stage -sidebar_label: Querying CSV File +sidebar_label: CSV --- ## Query CSV Files in Stage diff --git a/docs/en/guides/40-load-data/04-transform/02-querying-tsv.md b/docs/en/guides/40-load-data/04-transform/02-querying-tsv.md index 10df2fa6bc..d26afc1b23 100644 --- a/docs/en/guides/40-load-data/04-transform/02-querying-tsv.md +++ b/docs/en/guides/40-load-data/04-transform/02-querying-tsv.md @@ -1,6 +1,6 @@ --- title: Querying TSV Files in Stage -sidebar_label: Querying TSV File +sidebar_label: TSV --- ## Query TSV Files in Stage diff --git a/docs/en/guides/40-load-data/04-transform/03-querying-ndjson.md b/docs/en/guides/40-load-data/04-transform/03-querying-ndjson.md index 76f987a962..e134f9bc96 100644 --- a/docs/en/guides/40-load-data/04-transform/03-querying-ndjson.md +++ b/docs/en/guides/40-load-data/04-transform/03-querying-ndjson.md @@ -1,6 +1,6 @@ --- title: Querying NDJSON Files in Stage -sidebar_label: Querying NDJSON File +sidebar_label: NDJSON --- ## Query NDJSON Files in Stage diff --git a/docs/en/guides/40-load-data/04-transform/03-querying-orc.md b/docs/en/guides/40-load-data/04-transform/03-querying-orc.md index b4205cbf8e..b249738608 100644 --- a/docs/en/guides/40-load-data/04-transform/03-querying-orc.md +++ b/docs/en/guides/40-load-data/04-transform/03-querying-orc.md @@ -1,6 +1,6 @@ --- title: Querying Staged ORC Files in Stage -sidebar_label: Querying ORC File +sidebar_label: ORC --- import StepsWrap from '@site/src/components/StepsWrap'; import StepContent from '@site/src/components/Steps/step-content'; diff --git a/docs/en/guides/40-load-data/04-transform/04-querying-metadata.md b/docs/en/guides/40-load-data/04-transform/04-querying-metadata.md index ad1897fd6e..ee1c499bec 100644 --- a/docs/en/guides/40-load-data/04-transform/04-querying-metadata.md +++ b/docs/en/guides/40-load-data/04-transform/04-querying-metadata.md @@ -1,6 +1,6 @@ --- title: Query Metadata for Staged Files -sidebar_label: Querying Metadata +sidebar_label: Metadata --- ## Why and What is Metadata? From c08a8c897456749adef76c13802e564863fd8200 Mon Sep 17 00:00:00 2001 From: soyeric128 Date: Thu, 16 Jan 2025 08:05:08 -0500 Subject: [PATCH 09/10] updates --- docs/en/guides/41-migrate/mysql.md | 6 ++-- docs/en/guides/41-migrate/snowflake.md | 41 +++++++++++++++++++++++++ static/img/load/snowflake-databend.png | Bin 0 -> 86882 bytes 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 docs/en/guides/41-migrate/snowflake.md create mode 100644 static/img/load/snowflake-databend.png diff --git a/docs/en/guides/41-migrate/mysql.md b/docs/en/guides/41-migrate/mysql.md index 63dfb7595b..1d97150ee5 100644 --- a/docs/en/guides/41-migrate/mysql.md +++ b/docs/en/guides/41-migrate/mysql.md @@ -2,11 +2,11 @@ title: MySQL --- -This guide explains how to migrate data from MySQL to Databend. Databend supports two main migration approaches: batch loading and continuous data synchronization. +This guide introduces how to migrate data from MySQL to Databend. Databend supports two main migration approaches: batch loading and continuous data sync. ## Batch Loading -To migrate data from MySQL to Databend in batches, you can utilize tools such as Addax or DataX. +To migrate data from MySQL to Databend in batches, you can use tools such as Addax or DataX. ### Addax @@ -36,7 +36,7 @@ DatabendWriter supports two operational modes: INSERT (default) and REPLACE. In If you need more information about DatabendWriter and its functionalities, you can refer to the documentation available at https://github.com/alibaba/DataX/blob/master/databendwriter/doc/databendwriter.md -## Continuous Synchronization with CDC +## Continuous Sync with CDC To migrate data from MySQL to Databend in real-time, you can use Change Data Capture (CDC) tools such as Debezium or Flink CDC. diff --git a/docs/en/guides/41-migrate/snowflake.md b/docs/en/guides/41-migrate/snowflake.md new file mode 100644 index 0000000000..4e88c97f97 --- /dev/null +++ b/docs/en/guides/41-migrate/snowflake.md @@ -0,0 +1,41 @@ +--- +title: Snowflake +--- + +This guide provides a high-level overview of the process to migrate your data from Snowflake to Databend. The migration involves exporting data from Snowflake to an Amazon S3 bucket and then loading it into Databend. The process is broken down into three main steps: + +![alt text](@site/static/img/load/snowflake-databend.png) + +## Step 1: Configuring Snowflake Storage Integration for Amazon S3 + +Before exporting your data, you need to establish a connection between Snowflake and Amazon S3. This is achieved by configuring a storage integration that allows Snowflake to securely access and interact with the S3 bucket where your data will be staged. + +1. Create IAM Role & Policy: Start by creating an AWS IAM role with permissions to read from and write to your S3 bucket. This role ensures that Snowflake can interact with the S3 bucket securely. + +2. Snowflake Storage Integration: In Snowflake, you will configure a storage integration using the IAM role. This integration will allow Snowflake to securely access the designated S3 bucket and perform data export operations. + +3. Update Trust Relationships: After creating the storage integration, you will update the Trust Relationships of the IAM role in AWS to ensure that Snowflake can assume the IAM role and gain the necessary permissions for data access. + +## Step 2: Preparing & Exporting Data to Amazon S3 + +Once the integration is set up, the next step is to prepare the data within Snowflake and export it to the S3 bucket. + +1. Create Stage: You need to create an external stage in Snowflake that points to the S3 bucket. This stage will serve as a temporary location for the data before it's transferred to Databend. + +2. Prepare Data: Create the necessary tables and populate them with data in Snowflake. Once the data is ready, you can export it to the S3 bucket in a desired format, such as Parquet. + +3. Export Data: Use Snowflake’s COPY INTO command to export the data from Snowflake tables into the S3 bucket, specifying the file format and location. This process will save the data in the S3 bucket, making it ready for the next step. + +## Step 3: Loading Data into Databend + +Now that your data is exported to an S3 bucket, the final step is to load it into Databend. + +1. Create Target Table: In Databend, create a target table that matches the structure of the data you exported from Snowflake. + +2. Load Data: Use the COPY INTO command in Databend to load the data from the S3 bucket into the target table. Provide your AWS credentials to ensure Databend can access the S3 bucket. You can also define the file format (such as Parquet) to match the format of the exported data. + +3. Verify Data: After loading the data, perform a simple query in Databend to verify that the data has been successfully imported and is available for further processing. + +## Tutorials + +- [Migrating from Snowflake](/tutorials/migrate/migrating-from-snowflake) \ No newline at end of file diff --git a/static/img/load/snowflake-databend.png b/static/img/load/snowflake-databend.png new file mode 100644 index 0000000000000000000000000000000000000000..1ed705c6974f4c35daa00c248ebd0dfdda1551f6 GIT binary patch literal 86882 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 jz5n~kaNz&{yYR5t;SV13Wu%Buz(-0 Date: Thu, 16 Jan 2025 08:24:05 -0500 Subject: [PATCH 10/10] fix links --- docs/en/guides/40-load-data/02-load-db/addax.md | 5 +++++ docs/en/guides/40-load-data/02-load-db/datax.md | 5 +++++ docs/en/guides/40-load-data/02-load-db/debezium.md | 5 +++++ docs/en/guides/40-load-data/02-load-db/flink-cdc.md | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 docs/en/guides/40-load-data/02-load-db/addax.md create mode 100644 docs/en/guides/40-load-data/02-load-db/datax.md create mode 100644 docs/en/guides/40-load-data/02-load-db/debezium.md create mode 100644 docs/en/guides/40-load-data/02-load-db/flink-cdc.md diff --git a/docs/en/guides/40-load-data/02-load-db/addax.md b/docs/en/guides/40-load-data/02-load-db/addax.md new file mode 100644 index 0000000000..20c6fc4333 --- /dev/null +++ b/docs/en/guides/40-load-data/02-load-db/addax.md @@ -0,0 +1,5 @@ +--- +title: Addax +--- + +See [Addax](/guides/migrate/mysql#addax). \ No newline at end of file diff --git a/docs/en/guides/40-load-data/02-load-db/datax.md b/docs/en/guides/40-load-data/02-load-db/datax.md new file mode 100644 index 0000000000..0480a5ef75 --- /dev/null +++ b/docs/en/guides/40-load-data/02-load-db/datax.md @@ -0,0 +1,5 @@ +--- +title: DataX +--- + +See [DataX](/guides/migrate/mysql#datax). \ No newline at end of file diff --git a/docs/en/guides/40-load-data/02-load-db/debezium.md b/docs/en/guides/40-load-data/02-load-db/debezium.md new file mode 100644 index 0000000000..f0bdf06beb --- /dev/null +++ b/docs/en/guides/40-load-data/02-load-db/debezium.md @@ -0,0 +1,5 @@ +--- +title: Debezium +--- + +See [Debezium](/guides/migrate/mysql#debezium). \ No newline at end of file diff --git a/docs/en/guides/40-load-data/02-load-db/flink-cdc.md b/docs/en/guides/40-load-data/02-load-db/flink-cdc.md new file mode 100644 index 0000000000..6d70f2245f --- /dev/null +++ b/docs/en/guides/40-load-data/02-load-db/flink-cdc.md @@ -0,0 +1,5 @@ +--- +title: Flink CDC +--- + +See [Flink CDC](/guides/migrate/mysql#flink-cdc). \ No newline at end of file