📦 数据准备阶段
- 获取建表咒语
首先从 ClickHouse 数据库中提取建表 DDL,这就像是从古老魔书中抄录咒语。 - 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>
本文由 Ivan Dong 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Jul 16, 2025 at 08:28 am