从 ClickHouse 到 PostgreSQL:数据迁移的奇幻漂流
in Co-De with 0 comment

从 ClickHouse 到 PostgreSQL:数据迁移的奇幻漂流

in Co-De with 0 comment

📦 数据准备阶段

  1. 获取建表咒语
    首先从 ClickHouse 数据库中提取建表 DDL,这就像是从古老魔书中抄录咒语。
  2. AI 翻译魔法
    使用任意 AI 工具(推荐 GPT-4,它可是 SQL 翻译界的哈利波特)将 ClickHouse 的 DDL 翻译成 PostgreSQL 版本。注意!AI 可能会偷偷帮你优化命名风格,比如把驼峰命名法变成下划线命名法,就像把 "大驼峰" 变成 "小短腿" 一样自然。
-- ClickHouse原版咒语(带魔法特效)
CREATE TABLE bank_info ( 
    `opCode` String, 
    `shortCode` String, 
    `altCode` String, 
    `displayName` String, 
    `createTime` DateTime64(3) 
) ENGINE = MergeTree 
PARTITION BY createTime 
PRIMARY KEY opCode 
ORDER BY opCode 
SETTINGS index_granularity = 8192;

-- PostgreSQL翻译版(麻瓜也能看懂)
CREATE TABLE bank_info (
    op_code VARCHAR,
    short_code VARCHAR,
    alt_code VARCHAR,
    display_name VARCHAR,
    create_time TIMESTAMP(3),
    PRIMARY KEY (op_code)
);

-- 别忘了给时间字段加个索引,这就像给数据仓库装了个快递追踪器
CREATE INDEX idx_bank_info_create_time ON bank_info (create_time);

💡 注意这个神奇转换
AI 自动把字段名从驼峰(如createTime)改成了下划线(create_time)。这不是 AI 调皮,而是因为之前你可能多次要求 "驼峰转下划线",AI 已经记住你的喜好啦,就像贴心的咖啡师总是记得你要少糖一样!

🚀 技术思路:最快的数据传输魔法
PostgreSQL 导入数据最快的方式是通过 COPY 命令,就像用管道直接给数据库灌水。

数据传输介质选择 CSV 格式,这是数据界的 "通用 Esperanto 语"。

ClickHouse 支持导出 CSV,但需要通过命令行:
SELECT * FROM TABLE FORMAT CSV

不过我更推荐用代码读取数据并生成 CSV,这样能精确控制字段顺序,就像给数据排好队依次入场。

🧙♂️ 代码实现:数据迁移的魔法咒语

// 第一步:从ClickHouse读取数据(召唤数据精灵)
private static List<String> readDataFromClickHouse() throws SQLException {
    List<String> data = new ArrayList<>();
    try (Connection conn = DriverManager.getConnection(CLICKHOUSE_URL, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD);
         Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery("SELECT * FROM bank_info")) {
        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();
        while (rs.next()) {
            StringBuilder row = new StringBuilder();
            for (int i = 1; i <= columnCount; i++) {
                if (i > 1) row.append(",");
                row.append(rs.getString(i));
            }
            data.add(row.toString());
        }
    }
    return data;
}

// 第二步:把数据写入临时文件(把精灵封印在卷轴里)
private static String writeDataToTempFile(List<String> data) throws Exception {
    java.io.File tempFile = java.io.File.createTempFile("clickhouse_data", ".csv");
    try (java.io.FileWriter writer = new java.io.FileWriter(tempFile)) {
        for (String row : data) {
            writer.write(row + "\n");
        }
    }
    return tempFile.getAbsolutePath();
}

// 第三步:导入数据到PostgreSQL(解封精灵到新容器)
private static void importDataToPostgreSQL(String filePath) throws SQLException, java.io.IOException {
    try (Connection conn = DriverManager.getConnection(POSTGRESQL_URL, POSTGRESQL_USER, POSTGRESQL_PASSWORD)) {
        CopyManager copyManager = new CopyManager((BaseConnection) conn);
        String copyIn = "COPY bank_info FROM STDIN WITH (FORMAT CSV, DELIMITER ',')";
        try (java.io.FileReader fileReader = new java.io.FileReader(filePath);
             BufferedReader reader = new BufferedReader(fileReader)) {
            copyManager.copyIn(copyIn, reader);
        }
    }
}

// 依赖配置:别忘了带上这个魔法药剂配方
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.7</version>
</dependency>
Comments are closed.