Gunakan COPY FROM STDIN untuk memuat data ke Hologres dan COPY TO STDOUT untuk mengekspornya. Hologres memperluas sintaks COPY PostgreSQL standar dengan dua parameter khusus Hologres: STREAM_MODE (mode copy tetap) dan ON_CONFLICT (kebijakan konflik primary key).
Semua pernyataan COPY harus dijalankan melalui PostgreSQL client. Untuk detail koneksi, lihat PostgreSQL client.
Untuk memantau operasi COPY, kueri hologres.hg_query_log. Di Hologres V3.0 dan versi lebih baru, setiap operasi COPY menghasilkan dua catatan log—satu untuk perintah COPY dan satu untuk pernyataan INSERT yang mendasarinya—yang dihubungkan melalui ID transaksi. Lihat Query log untuk detailnya.
Batasan
COPY FROMhanya menulis ke tabel partisi anak, bukan tabel partisi induk.COPY FROM STDINmendukung tabel dengan kendala DEFAULT atau kolom SERIAL mulai dari Hologres V1.1.43. Versi sebelumnya tidak mendukung jenis tabel ini.
Sintaks
/* Impor data */
COPY table_name [ ( column_name [, ...] ) ]
FROM STDIN
[ [ WITH ] ( option [, ...] ) ]
/* Ekspor data */
COPY { ( query ) }
TO STDOUT
[ [ WITH ] ( option [, ...] ) ]Dengan option dapat berupa salah satu berikut:
FORMAT format_name -- TEXT (default), CSV, atau BINARY
DELIMITER 'delimiter_character'
NULL 'null_string'
HEADER [ boolean ] -- hanya CSV
QUOTE 'quote_character' -- hanya CSV
ESCAPE 'escape_character' -- hanya CSV
FORCE_QUOTE { ( column_name [, ...] ) | * } -- CSV, hanya COPY TO
FORCE_NOT_NULL ( column_name [, ...] ) -- CSV, hanya COPY FROM
ENCODING 'encoding_name'
STREAM_MODE [ boolean ] -- khusus Hologres; hanya COPY FROM
ON_CONFLICT 'none|ignore|update' -- khusus Hologres; hanya COPY FROMParameter
| Parameter | Deskripsi |
|---|---|
table_name | Tabel Hologres tempat mengimpor data. |
query | Pernyataan SELECT yang hasilnya diekspor. |
STDIN | Membaca input dari standard input klien. |
STDOUT | Menulis output ke standard output klien. |
FORMAT | Format file: TEXT (default), CSV, atau BINARY. Impor BINARY hanya didukung dalam mode copy tetap (STREAM_MODE TRUE). |
DELIMITER | Pemisah kolom. Default: tab (\t) untuk TEXT, koma (,) untuk CSV. Contoh: DELIMITER AS ','. |
NULL | String yang merepresentasikan nilai null. Default: \N untuk TEXT, string kosong tanpa tanda kutip untuk CSV. Tidak didukung untuk BINARY. |
HEADER | Apakah file mencakup baris header. Hanya untuk CSV. |
QUOTE | Karakter satu byte yang digunakan untuk mengapit nilai bidang. Hanya untuk CSV. Default: ". |
ESCAPE | Karakter satu byte yang mendahului kecocokan QUOTE. Hanya untuk CSV. Default: sama dengan QUOTE. |
FORCE_QUOTE | Mewajibkan pengutipan untuk semua nilai non-NULL di kolom yang ditentukan. Berlaku hanya untuk CSV dan COPY TO. |
FORCE_NOT_NULL | Memperlakukan string representasi null sebagai string dengan panjang nol, bukan NULL. CSV, hanya untuk COPY FROM. |
ENCODING | Enkoding file. Default: enkoding klien. |
STREAM_MODE | Mengaktifkan mode copy tetap untuk impor. Default: FALSE. Ketika TRUE, menggunakan rencana eksekusi tetap dengan lock tingkat baris alih-alih lock tingkat tabel. Hanya untuk COPY FROM. |
ON_CONFLICT | Kebijakan konflik saat terjadi tabrakan primary key. Nilainya tidak peka huruf besar/kecil tanpa tanda kutip; dengan tanda kutip tunggal, gunakan huruf kecil (misalnya, 'none'). Hanya untuk COPY FROM. Lihat Perilaku ON_CONFLICT berdasarkan versi. |
Nilai ON_CONFLICT:
| Nilai | Perilaku | Kapan digunakan |
|---|---|---|
NONE | Melaporkan error saat terjadi konflik. | Integritas data ketat — setiap baris harus baru. |
IGNORE | Melewatkan baris yang konflik. | Pemuatan idempoten di mana duplikat diharapkan dan catatan yang ada harus dipertahankan. |
UPDATE | Menimpa baris yang konflik. | Pola upsert di mana nilai terbaru yang menang. |
Perilaku ON_CONFLICT berdasarkan versi
Sebelum V3.0.4:
ON_CONFLICThanya berlaku ketikaSTREAM_MODE TRUE.V3.0.4 dan versi lebih baru:
ON_CONFLICTjuga berlaku ketikaSTREAM_MODE FALSE, dengan parameter GUChg_experimental_copy_enable_on_conflictdiaktifkan. KetikaSTREAM_MODE FALSE,UPDATEmemerlukan penulisan semua kolom.V3.1.1 dan versi lebih baru: Ketika
STREAM_MODE FALSE,UPDATEmendukung impor parsial-kolom (hg_experimental_copy_enable_on_conflictdiaktifkan secara default).
Atomicitas
COPY standar (STREAM_MODE FALSE) menjamin atomicitas: seluruh operasi berhasil atau dikembalikan (rollback).
Mode copy tetap (STREAM_MODE TRUE) menggunakan lock tingkat baris alih-alih lock tingkat tabel, sehingga atomicitas tidak dijamin. Jika suatu baris berisi data tidak valid, error dilaporkan hanya untuk baris tersebut—baris lainnya mungkin sebagian tertulis atau tidak tertulis sama sekali.
Query log
Di Hologres V3.0 dan versi lebih baru, setiap operasi COPY menghasilkan dua catatan di hologres.hg_query_log: satu untuk perintah COPY dan satu untuk INSERT yang dijalankannya secara internal. Hubungkan keduanya menggunakan ID transaksi:
SELECT
query_id,
query,
extended_info
FROM
hologres.hg_query_log
WHERE
extended_info ->> 'source_trx' = '<transaction_id>' -- Dapatkan ID transaksi dari field trans_id dalam catatan log COPY
ORDER BY
query_start;Pada versi sebelum V3.0, setiap operasi COPY menghasilkan satu catatan saja.
Impor data ke Hologres
Impor dari PostgreSQL client (stdin)
PostgreSQL client hanya dapat membaca dari stdin. Konsol HoloWeb tidak mendukung impor stdin.
Contoh 1: Impor teks berpemisah
-- Buat tabel target
CREATE TABLE copy_test (
id int,
age int,
name text
);
-- Impor data dari stdin
COPY copy_test FROM STDIN WITH DELIMITER AS ',' NULL AS '';
53444,24,wangming
55444,38,ligang
55444,38,luyong
\.
-- Verifikasi
SELECT * FROM copy_test;Contoh 2: Impor file CSV
-- Buat tabel target
CREATE TABLE partsupp (
ps_partkey integer NOT NULL,
ps_suppkey integer NOT NULL,
ps_availqty integer NOT NULL,
ps_supplycost float NOT NULL,
ps_comment text NOT NULL
);
-- Impor CSV dari stdin
COPY partsupp FROM STDIN WITH DELIMITER '|' CSV;
1|2|3325|771.64|final theodolites
1|25002|8076|993.49|ven ideas
\.
-- Verifikasi
SELECT * FROM partsupp;Contoh 3: Impor file lokal menggunakan psql
Arahkan file lokal ke stdin dengan operator redirect shell psql:
psql -U <username> -p <port> -h <endpoint> -d <databasename> \
-c "COPY <table> FROM STDIN WITH DELIMITER '|' CSV;" <<filename>;| Parameter | Deskripsi | Contoh |
|---|---|---|
username | Akun Alibaba Cloud: ID AccessKey. Akun kustom: username (misalnya, BASIC$abc). Simpan ID AccessKey dalam variabel lingkungan untuk menghindari eksposurnya dalam perintah. | — |
port | Port publik instans Hologres. | 80 |
endpoint | Titik akhir publik instans Hologres. | xxx-cn-hangzhou.hologres.aliyuncs.com |
databasename | Nama database Hologres. | mydb |
table | Nama tabel target. | — |
filename | Path ke file lokal. | D:\tmp\copy_test.csv |
Contoh berikut mengimpor file lokal copy_test menggunakan perintah ini:

File berisi:
01,01,name1
02,01,name2
03,01,name3
04,01,name4Setelah impor, kueri hasilnya di psql:

Impor dari klien JDBC menggunakan CopyManager
Klien Java Database Connectivity (JDBC) dapat menggunakan CopyManager—wrapper API driver JDBC PostgreSQL untuk COPY—untuk mengalirkan file ke Hologres.
package com.aliyun.hologram.test.jdbc;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
import org.postgresql.copy.CopyManager;
import org.postgresql.core.BaseConnection;
public class jdbcCopyFile {
public static void main(String args[]) throws Exception {
System.out.println(copyFromFile(getConnection(), "/Users/feng/Workspace/region.tbl", "region"));
}
public static Connection getConnection() throws Exception {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://endpoint:port/dbname";
Properties props = new Properties();
// Simpan kredensial dalam variabel lingkungan untuk menghindari hardcoding
props.setProperty("user", "AAA"); // ID AccessKey
props.setProperty("password", "BBB"); // Rahasia AccessKey
return DriverManager.getConnection(url, props);
}
/**
* Mengalirkan file lokal ke Hologres melalui COPY FROM STDIN.
*
* @param connection Koneksi JDBC aktif
* @param filePath Path ke file lokal
* @param tableName Tabel Hologres target
* @return Jumlah baris yang diimpor
*/
public static long copyFromFile(Connection connection, String filePath, String tableName)
throws SQLException, IOException {
long count = 0;
FileInputStream fileInputStream = null;
try {
CopyManager copyManager = new CopyManager((BaseConnection) connection);
fileInputStream = new FileInputStream(filePath);
count = copyManager.copyIn("COPY " + tableName + " FROM STDIN delimiter '|' csv", fileInputStream);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return count;
}
}Mode copy tetap
Mode copy tetap (STREAM_MODE TRUE) menggunakan rencana eksekusi tetap yang telah dikompilasi sebelumnya untuk mempercepat impor COPY berulang. Ini adalah optimisasi khusus Hologres yang tersedia sejak V1.3.17 dan hanya berlaku untuk impor. Untuk perbandingan dengan mode penulisan batch lainnya, lihat Perbandingan mode penulisan batch. Untuk mekanisme dasarnya, lihat Percepat eksekusi SQL dengan rencana tetap.
Menulis ke subset kolom — pembaruan parsial
Ketika ON_CONFLICT UPDATE diatur dan COPY hanya menulis ke beberapa kolom, kolom yang tidak termasuk dalam daftar COPY tidak dimodifikasi:
CREATE TABLE t0 (id int NOT NULL, name text, age int, primary key(id));
COPY t0(id, name) FROM STDIN
WITH (
STREAM_MODE TRUE,
ON_CONFLICT UPDATE
);
-- Pernyataan INSERT INTO yang setara:
INSERT INTO t0(id, name) VALUES(?, ?)
ON CONFLICT(id) DO UPDATE SET
id = excluded.id, name = excluded.name;Menulis ke subset kolom — kolom dengan nilai default
Ketika kolom yang tidak termasuk dalam daftar COPY memiliki nilai DEFAULT, Hologres menerapkan nilai default hanya untuk baris baru. Baris yang sudah ada dan cocok berdasarkan primary key tidak diperbarui untuk kolom tersebut:
CREATE TABLE t0 (id int NOT NULL, name text, age int DEFAULT 0, primary key(id));
COPY t0(id, name) FROM STDIN
WITH (
STREAM_MODE TRUE,
ON_CONFLICT UPDATE
);
-- Pernyataan INSERT INTO yang setara:
-- Untuk baris baru (tidak ada id yang cocok), age diatur ke nilai default-nya.
-- Untuk baris yang sudah ada (id yang cocok), age tidak diperbarui.
INSERT INTO t0(id, name, age) VALUES(?, ?, DEFAULT)
ON CONFLICT(id) DO UPDATE SET
id = excluded.id, name = excluded.name;Ekspor data dari Hologres
Ekspor ke file lokal
Kedua metode berikut hanya tersedia pada PostgreSQL client.
Menggunakan meta-perintah `\copy` (psql)
-- Buat dan isi tabel
CREATE TABLE copy_to_local (
id int,
age int,
name text
);
INSERT INTO copy_to_local VALUES
(1, 1, 'a'),
(1, 2, 'b'),
(1, 3, 'c'),
(1, 4, 'd');
-- Ekspor ke file lokal
\COPY (SELECT * FROM copy_to_local) TO '/root/localfile.txt';Menggunakan pengalihan stdout (psql)
psql -U <username> -p <port> -h <endpoint> -d <databasename> \
-c "COPY (SELECT * FROM <tablename>) TO STDOUT WITH DELIMITER '|' CSV;" > <filename>Ekspor ke Object Storage Service (OSS)
Gunakan program hg_dump_to_oss dengan COPY TO PROGRAM untuk mengekspor data Hologres ke bucket OSS. Setiap ekspor dibatasi hingga 5 GB.
Prasyarat
Hanya superuser dan pengguna dengan role pg_execute_server_program yang dapat menjalankan hg_dump_to_oss. Berikan role tersebut sebagai berikut:
-- Model izin sederhana (SPM)
CALL spm_grant('pg_execute_server_program', '<ID akun Alibaba Cloud, alamat email, atau akun Pengguna RAM>');
-- Model otorisasi PostgreSQL standar
GRANT pg_execute_server_program TO <account>;Sintaks
COPY (query) TO PROGRAM 'hg_dump_to_oss
--AccessKeyId <access_key_id>
--AccessKeySecret <access_key_secret>
--Endpoint <oss_classic_network_endpoint>
--BucketName <bucket_name>
--DirName <directory>
[--FileName <file_name>]
[--BatchSize <n>]'
(DELIMITER ',', HEADER true, FORMAT CSV);DirName tidak boleh diawali dengan / atau \.
Parameter
| Parameter | Deskripsi | Contoh | |
|---|---|---|---|
query | Pernyataan SELECT yang hasilnya diekspor. | SELECT * FROM dual; | |
AccessKeyId | ID AccessKey. Simpan dalam variabel lingkungan untuk menghindari eksposur kredensial. | — | |
AccessKeySecret | Rahasia AccessKey. Simpan dalam variabel lingkungan. | — | |
Endpoint | Titik akhir jaringan klasik bucket OSS. Gunakan titik akhir jaringan klasik, bukan titik akhir publik atau VPC. Temukan di halaman detail bucket atau di Wilayah dan titik akhir OSS. | oss-cn-beijing-internal.aliyuncs.com | |
BucketName | Nama bucket OSS. | dummy_bucket | |
DirName | Path direktori OSS. Tidak boleh diawali dengan / atau \. | testdemo/ | |
FileName | (Opsional) Nama file output. Tidak boleh mengandung: `` ; # ' | ? ~ < ( ) " $ \ { } [ ] & * \n \r ``. | file_name |
BatchSize | Baris yang diproses per batch. Default: 1000. | 5000 | |
DELIMITER | Pemisah bidang dalam file output. Default: tab (\t). | , |
Contoh
-- Ekspor dari tabel internal Hologres ke OSS
COPY (SELECT * FROM holo_test LIMIT 2)
TO PROGRAM 'hg_dump_to_oss
--AccessKeyId <access_id>
--AccessKeySecret <access_key>
--Endpoint oss-cn-hangzhou-internal.aliyuncs.com
--BucketName hologres-demo
--DirName holotest/
--FileName file_name
--BatchSize 3000'
DELIMITER ',';
-- Ekspor dari tabel eksternal Hologres ke OSS
COPY (SELECT * FROM foreign_holo_test LIMIT 20)
TO PROGRAM 'hg_dump_to_oss
--AccessKeyId <access_id>
--AccessKeySecret <access_key>
--Endpoint oss-cn-hangzhou-internal.aliyuncs.com
--BucketName hologres-demo
--DirName holotest/
--FileName file_name
--BatchSize 3000'
(DELIMITER ',', HEADER true);
-- Ekspor ke bucket OSS di wilayah berbeda
-- (misalnya, dari instans Hologres di Tiongkok (Hangzhou) ke bucket OSS di Tiongkok (Beijing))
COPY (SELECT * FROM holo_test_1 LIMIT 20)
TO PROGRAM 'hg_dump_to_oss
--AccessKeyId <access_id>
--AccessKeySecret <access_key>
--Endpoint oss-cn-beijing-internal.aliyuncs.com
--BucketName hologres-demo
--DirName holotest/
--FileName file_name
--BatchSize 3000'
(DELIMITER ',', HEADER true, FORMAT CSV);Pemecahan Masalah
| Error | Penyebab | Solusi |
|---|---|---|
ERROR: syntax error at or near ")" LINE 1: COPY (select 1,2,3 from ) TO PROGRAM 'hg_dump_to_oss2 --Acce... | Parameter query berisi pernyataan SQL tidak valid. | Perbaiki sintaks kueri. |
DETAIL: child process exited with exit code 255 | Titik akhir OSS menggunakan jenis jaringan yang salah. | Gunakan titik akhir jaringan klasik bucket OSS. |
DETAIL: command not found | Argumen PROGRAM tidak diatur ke hg_dump_to_oss. | Perbaiki nama program. |
DETAIL: child process exited with exit code 101 | ID AccessKeyId tidak valid. | Gunakan ID AccessKey yang valid. |
DETAIL: child process exited with exit code 102 | Rahasia AccessKeySecret tidak valid. | Gunakan rahasia AccessKey yang benar. |
DETAIL: child process exited with exit code 103 | Titik akhir Endpoint tidak valid. | Gunakan titik akhir jaringan klasik untuk bucket OSS. |
DETAIL: child process exited with exit code 104 | Nama BucketName tidak valid. | Verifikasi nama bucket. |
DETAIL: child process exited with exit code 105 | Parameter yang diperlukan tidak ada. | Pastikan semua parameter yang diperlukan telah ditentukan. |
ERROR: program "hg_dump_to_oss ..." failed DETAIL: child process exited with exit code 255 | Instans Hologres tidak dapat menjangkau jaringan OSS. | Beralih ke titik akhir jaringan klasik. Untuk detail titik akhir, lihat Wilayah dan titik akhir OSS. |
Ekspor dari klien JDBC menggunakan CopyManager
import org.postgresql.copy.CopyManager;
import org.postgresql.core.BaseConnection;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class copy_to_local_file {
public static void main(String args[]) throws Exception {
System.out.println(copyToFile(getConnection(), "/Users/feng/Workspace/region.tbl", "select * from region"));
}
public static Connection getConnection() throws Exception {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://endpoint:port/dbname";
Properties props = new Properties();
// Simpan kredensial dalam variabel lingkungan untuk menghindari hardcoding
props.setProperty("user", "AAA"); // ID AccessKey
props.setProperty("password", "BBB"); // Rahasia AccessKey
return DriverManager.getConnection(url, props);
}
/**
* Mengalirkan hasil kueri Hologres ke file lokal melalui COPY TO STDOUT.
*
* @param connection Koneksi JDBC aktif
* @param filePath Path file tujuan
* @param SQL_Query Pernyataan SELECT untuk diekspor
* @return Path file yang ditulis
*/
public static String copyToFile(Connection connection, String filePath, String SQL_Query)
throws SQLException, IOException {
FileOutputStream fileOutputStream = null;
try {
CopyManager copyManager = new CopyManager((BaseConnection) connection);
fileOutputStream = new FileOutputStream(filePath);
copyManager.copyOut("COPY (" + SQL_Query + ") TO STDOUT DELIMITER '|' csv", fileOutputStream);
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return filePath;
}
}Langkah Selanjutnya
Ikhtisar tipe data — Tipe data yang didukung untuk operasi COPY
Percepat eksekusi SQL dengan rencana tetap — Cara kerja rencana tetap
Perbandingan mode penulisan batch — Kapan menggunakan COPY vs metode penulisan lainnya