Dokumen ini menjelaskan cara menggunakan pernyataan INSERT ON CONFLICT di Hologres.
Skenario
Perintah INSERT ON CONFLICT cocok untuk skenario impor data menggunakan pernyataan SQL.
Saat menulis data menggunakan Data Integration atau Flink, Anda dapat mengonfigurasi pengaturan berikut untuk memperbarui atau melewatkan baris yang memiliki primary key duplikat:
-
Impor data menggunakan fitur Data Integration dari DataWorks.
Data Integration memiliki fitur bawaan
INSERT ON CONFLICT. Untuk informasi selengkapnya tentang cara kerja fitur ini, lihat Hologres Writer. Anda dapat mengonfigurasi pengaturan berikut:-
Untuk sinkronisasi data offline, atur Write Conflict Policy menjadi Ignore atau Replace.
-
Untuk sinkronisasi data real-time, Anda dapat mengatur Write Conflict Policy menjadi Ignore atau Replace.
CatatanUntuk memperbarui data selama sinkronisasi, Anda harus menetapkan primary key untuk tabel Hologres.
-
-
Tulis data menggunakan Flink.
Saat menulis data menggunakan Flink, write conflict policy default adalah
InsertOrIgnore. Kebijakan ini mengharuskan Anda menetapkan primary key untuk tabel Hologres dan menyimpan entri data pertama sambil mengabaikan semua entri duplikat berikutnya. Jika Anda menggunakan sintaksisctas, write conflict policy default adalahInsertOrUpdate, yang menggantikan data yang ada.
Pengenalan perintah
Pernyataan INSERT ON CONFLICT menyisipkan satu baris data ke kolom yang ditentukan. Jika terdapat baris dengan primary key duplikat, pernyataan tersebut akan memperbarui baris yang ada atau melewatkan penyisipan, sehingga menyediakan fungsionalitas UPSERT (INSERT atau UPDATE). Sintaks pernyataan INSERT ON CONFLICT adalah sebagai berikut.
INSERT INTO <table_name> [ AS <alias> ] [ ( <column_name> [, ...] ) ]
{ VALUES ( { <expression> } [, ...] ) [, ...] | <query> }
[ ON CONFLICT [ conflict_target ] conflict_action ]
where conflict_target is pk
ON CONSTRAINT constraint_name
and conflict_action is one of:
DO NOTHING
DO UPDATE SET { <column_name> = { <expression> } |
( <column_name> [, ...] ) = ( { <expression> } [, ...] ) |
} [, ...]
[ WHERE condition ]
Tabel berikut menjelaskan parameter-parameter tersebut.
Parameter | Deskripsi |
table_name |
Nama tabel tujuan tempat data dimasukkan. |
alias |
Alias. Ini adalah nama alternatif untuk tabel tujuan. |
column_name |
Nama kolom target di tabel tujuan. |
DO NOTHING |
InsertOrIgnore. Jika terdapat baris dengan primary key duplikat saat menyisipkan baris ke kolom yang ditentukan, penyisipan dilewati. |
DO UPDATE |
InsertOrUpdate. Jika terdapat baris dengan primary key duplikat saat menyisipkan baris ke kolom yang ditentukan, baris yang ada diperbarui. Kasus-kasus berikut berlaku:
Penting
|
expression |
Ekspresi yang akan dieksekusi untuk kolom yang sesuai. Anda dapat menyetel ekspresi ini dengan merujuk pada PostgreSQL. Ekspresi umum meliputi |
Cara Kerja
Fitur INSERT ON CONFLICT bekerja serupa dengan pernyataan UPDATE. Untuk informasi selengkapnya, lihat UPDATE. Proses pembaruan sedikit berbeda tergantung pada format penyimpanan tabel—berorientasi baris, berorientasi kolom, atau hibrida baris-kolom—yang berdampak pada kinerja saat memperbarui tabel dengan format penyimpanan berbeda. Berdasarkan kebutuhan bisnis Anda, INSERT ON CONFLICT dapat dikategorikan sebagai InsertOrIgnore, InsertOrReplace, atau InsertOrUpdate. Tabel berikut menjelaskan perbedaannya.
Mode Pembaruan | Deskripsi |
InsertOrIgnore |
Mengabaikan pembaruan selama penulisan. Jika tabel sink memiliki primary key dan ditemukan primary key duplikat selama penulisan real-time, data yang datang belakangan dibuang. Ini diimplementasikan menggunakan |
InsertOrUpdate |
Memperbarui data selama penulisan. Jika tabel sink memiliki primary key dan ditemukan primary key duplikat selama penulisan real-time, data diperbarui berdasarkan primary key. Mode ini mencakup pembaruan seluruh baris dan pembaruan kolom parsial. Dalam pembaruan kolom parsial, jika baris masuk tidak berisi semua kolom, kolom yang tidak disebutkan tidak diperbarui. Ini diimplementasikan menggunakan |
InsertOrReplace |
Menimpa data selama penulisan. Jika tabel sink memiliki primary key dan ditemukan primary key duplikat selama penulisan real-time, data diperbarui berdasarkan primary key. Jika baris masuk tidak berisi semua kolom, kolom yang tidak disebutkan diisi dengan nilai null. Ini diimplementasikan menggunakan |
Berdasarkan cara kerja pernyataan UPDATE, kinerja pembaruan dalam mode yang berbeda bervariasi tergantung pada format penyimpanan tabel:
-
Kinerja mode penulisan berbeda untuk tabel berorientasi kolom diurutkan sebagai berikut:
-
Kinerja tertinggi jika tabel sink tidak memiliki primary key.
-
Jika tabel sink memiliki primary key:
InsertOrIgnore > InsertOrReplace >= InsertOrUpdate (full row) > InsertOrUpdate (partial column).
-
-
Kinerja mode penulisan berbeda untuk tabel berorientasi baris diurutkan sebagai berikut:
InsertOrReplace = InsertOrUpdate (full row) >= InsertOrUpdate (partial column) >= InsertOrIgnore.
Batasan
-
Kondisi dalam pernyataan
INSERT ON CONFLICTharus mencakup semua primary key. -
Saat Hologres High-QPS Engine (HQE) mengeksekusi pernyataan INSERT ON CONFLICT, urutan operasi tidak dijamin. Oleh karena itu, Anda tidak dapat mencapai semantik keep-first atau keep-last. Perilakunya adalah keep-any. Dalam praktiknya, jika sumber data berisi primary key duplikat yang perlu dihapus, Anda dapat menggunakan semantik keep-last dengan menjalankan perintah berikut:
-- Simpan baris terakhir dari baris duplikat. set hg_experimental_affect_row_multiple_times_keep_last = on;
Contoh
-
Contoh penggunaan pernyataan
INSERT ON CONFLICT:CatatanHologres V2.1.17 dan versi yang lebih baru mendukung Serverless Computing. Untuk skenario seperti impor data offline berskala besar, pekerjaan extract, transform, and load (ETL) besar, dan kueri volume besar pada tabel eksternal, Anda dapat menggunakan Serverless Computing untuk mengeksekusi tugas-tugas tersebut. Fitur ini menggunakan sumber daya serverless tambahan alih-alih sumber daya instans Anda sendiri. Anda tidak perlu menyediakan sumber daya komputasi tambahan untuk instans Anda. Hal ini secara signifikan meningkatkan stabilitas instans, mengurangi kemungkinan error out-of-memory (OOM), dan Anda hanya dikenai biaya untuk setiap tugas individual. Untuk informasi selengkapnya tentang Serverless Computing, lihat Serverless Computing. Untuk informasi tentang cara menggunakan Serverless Computing, lihat Panduan penggunaan Serverless Computing.
-
Persiapkan tabel dan data:
begin ; create table test1 ( a int NOT NULL PRIMARY KEY, b int, c int ); commit ; insert into test1 values (1,2,3); -
Lihat contoh untuk skenario berbeda:
CatatanContoh skenario berikut bersifat independen satu sama lain. Mereka tidak berurutan dan semuanya didasarkan pada tabel dan data yang dibuat pada langkah sebelumnya.
-
Skenario 1: Terapkan operasi InsertOrIgnore. Jika terdapat primary key duplikat, baris tidak diperbarui.
INSERT INTO test1 (a, b, c) VALUES (1, 1, 1) ON CONFLICT (a) DO NOTHING; -- Data dalam tabel test1 setelah pembaruan: a b c 1 2 3 -
Skenario 2: Terapkan operasi InsertOrUpdate untuk pembaruan seluruh baris. Anda dapat menggunakan salah satu metode berikut:
-
Metode 1: Cantumkan semua kolom dalam klausa
SET..EXCLUDED.INSERT INTO test1 (a, b, c) VALUES (1, 1, 1) ON CONFLICT (a) DO UPDATE SET b = EXCLUDED.b, c = EXCLUDED.c; -- Data dalam tabel test1 setelah pembaruan: a b c 1 1 1 -
Metode 2: Gunakan
ROW(EXCLUDED.*)untuk memperbarui semua kolom.INSERT INTO test1 (a, b, c)VALUES (1, 1, 1) ON CONFLICT (a) DO UPDATE SET (a,b,c) = ROW(EXCLUDED.*); -- Data dalam tabel test1 setelah pembaruan: a b c 1 1 1
-
-
Skenario 3: Terapkan operasi InsertOrUpdate untuk pembaruan kolom parsial. Hanya kolom yang ditentukan yang diperbarui, dan kolom yang tidak disebutkan tidak diperbarui.
-- Untuk melakukan pembaruan kolom parsial, cantumkan kolom yang ingin Anda perbarui setelah SET. INSERT INTO test1 (a, b, c) VALUES (1, 1, 1) ON CONFLICT (a) DO UPDATE SET b = EXCLUDED.b; -- Kolom c dalam tabel tidak diperbarui. Data dalam tabel test1 setelah pembaruan: a b c 1 1 3 -
Skenario 4: Terapkan operasi InsertOrReplace. Ini menimpa seluruh baris. Jika kolom tidak disebutkan, kolom tersebut diisi dengan nilai null.
-- Untuk menerapkan operasi InsertOrReplace di mana kolom yang tidak disebutkan diisi dengan null, Anda harus secara manual memberikan null dalam nilai insert. INSERT INTO test1 (a, b,c) VALUES (1, 1,null) ON CONFLICT (a) DO UPDATE SET b = EXCLUDED.b,c = EXCLUDED.c; -- Data dalam tabel test1 setelah pembaruan: a b c 1 1 \N -
Skenario 5: Perbarui data dalam tabel test1 dari tabel lain bernama test2.
-- Persiapkan tabel test2 dan data. CREATE TABLE test2 ( d int NOT NULL PRIMARY KEY, e int, f int ); INSERT INTO test2 VALUES (1, 5, 6); -- Ganti baris dalam tabel test1 dengan baris dari tabel test2 yang memiliki primary key yang sama. INSERT INTO test1 (a, b, c) SELECT d,e,f FROM test2 ON CONFLICT (a) DO UPDATE SET (a,b,c) = ROW (excluded.*); -- Data dalam tabel test1 setelah pembaruan: a b c 1 5 6 -- Ganti baris dalam tabel test1 dengan baris dari tabel test2 yang memiliki primary key yang sama, tetapi sesuaikan pemetaan pembaruan. Kolom e dari test2 memperbarui kolom c, dan kolom f dari test2 memperbarui kolom b. INSERT INTO test1 (a, b, c) SELECT d,e,f FROM test2 ON CONFLICT (a) DO UPDATE SET (a,c,b) = ROW (excluded.*); -- Data dalam tabel test1 setelah pembaruan: a b c 1 6 5
-
-
-
Optimalisasi untuk pernyataan
INSERT ON CONFLICTpada tabel berorientasi baris:Hologres mengoptimalkan pembaruan untuk tabel berorientasi baris. Untuk kinerja terbaik, pertahankan urutan kolom dalam klausa UPDATE konsisten dengan urutan dalam klausa INSERT dan lakukan pembaruan seluruh baris.
INSERT INTO test1 (a, b, c) SELECT d,e,f FROM test2 ON CONFLICT (a) DO UPDATE SET a = excluded.a, b = excluded.b, c = excluded.c; INSERT INTO test1 (a, b, c) SELECT d,e,f FROM test2 ON CONFLICT (a) DO UPDATE SET(a,b,c) = ROW (excluded.*)
Error umum
-
Gejala
Salah satu dari tiga error berikut terjadi saat Anda mengeksekusi pernyataan
INSERT ON CONFLICTpada sumber data:-
Error 1:
duplicate key value violates unique constraint. -
Error 2:
Update row with Key (xxx)=(yyy) multiple times. -
Error 3 (masalah OOM):
Total memory used by all existing queries exceeded memory limitation.
-
-
Penyebab 1: Sumber data berisi data duplikat.
Hologres kompatibel dengan PostgreSQL dan menggunakan sintaks standar PostgreSQL. Menurut semantik standar PostgreSQL, sumber data tidak boleh berisi data duplikat saat Anda mengeksekusi pernyataan
INSERT ON CONFLICT. Jika sumber data berisi data duplikat, salah satu error di atas akan terjadi.CatatanData duplikat dalam sumber data berarti data yang akan dimasukkan berisi baris duplikat, bukan bahwa data yang akan dimasukkan memiliki duplikat di tabel tujuan.
Contoh berikut menunjukkan pernyataan
INSERT ON CONFLICTdi mana data yang akan dimasukkan berisi baris duplikat:INSERT INTO test1 VALUES (1, 2, 3), (1, 2, 3) ON CONFLICT (a) DO UPDATE SET (a, b, c) = ROW (excluded.*);Solusi:
Jika sumber data berisi data duplikat, Anda dapat mengonfigurasi parameter berikut untuk menyimpan baris terakhir dari baris duplikat:
set hg_experimental_affect_row_multiple_times_keep_last = on; -
Penyebab 2: Sumber data berisi data duplikat karena masa hidup data (TTL) telah kedaluwarsa.
Tabel dalam sumber data memiliki time to live (TTL) yang dikonfigurasi. Beberapa data dalam tabel telah melebihi TTL-nya. Karena pembersihan TTL tidak instan, data yang kedaluwarsa mungkin tidak segera dihapus. Hal ini dapat menyebabkan data primary key (PK) duplikat selama impor, yang mengakibatkan error.
Solusi:
Mulai dari Hologres V1.3.23, Anda dapat menggunakan perintah berikut untuk memperbaiki dengan cepat data PK duplikat yang disebabkan oleh TTL yang kedaluwarsa. Saat menjalankan perintah ini, sistem menghapus data PK duplikat dari tabel. Kebijakan pembersihan default adalah Keep Last, yang menyimpan baris terakhir yang ditulis di antara duplikat dan menghapus yang lainnya.
Catatan-
Secara prinsip, PK seharusnya tidak diduplikasi. Oleh karena itu, perintah ini hanya membersihkan PK duplikat yang disebabkan oleh TTL yang kedaluwarsa.
-
Perintah ini hanya tersedia di Hologres V1.3.23 dan versi yang lebih baru. Jika instans Anda menggunakan versi sebelumnya, Anda harus melakukan upgrade instans.
call public.hg_remove_duplicated_pk('<schema>.<table_name>');Contoh: Asumsikan Anda memiliki dua tabel.
tbl_1adalah tabel tujuan, dantbl_2adalah tabel sumber dengan TTL300s. Anda ingin memperbaruitbl_1dengan semua data daritbl_2. Setelah TTL berakhir, primary key duplikat muncul ditbl_2, yang menyebabkan error.BEGIN; CREATE TABLE tbl_1 ( a int NOT NULL PRIMARY KEY, b int, c int ); CREATE TABLE tbl_2 ( d int NOT NULL PRIMARY KEY, e int, f int ); CALL set_table_property('tbl_2', 'time_to_live_in_seconds', '300'); COMMIT; INSERT INTO tbl_1 VALUES (1, 1, 1), (2, 3, 4); INSERT INTO tbl_2 VALUES (1, 5, 6); -- Setelah 300s, masukkan data ke tbl_2 lagi. INSERT INTO tbl_2 VALUES (1, 3, 6); -- Ganti baris di tbl_1 dengan baris dari tbl_2 yang memiliki primary key yang sama. Pembaruan gagal karena PK duplikat yang disebabkan oleh TTL yang kedaluwarsa. INSERT INTO tbl_1 (a, b, c) SELECT d,e,f FROM tbl_2 ON CONFLICT (a) DO UPDATE SET (a,b,c) = ROW (excluded.*); -- Penyebab error: ERROR: internal error: Duplicate keys detected when building hash table. -- Gunakan perintah untuk membersihkan data PK duplikat di tbl_2. Kebijakannya adalah keep last. call public.hg_remove_duplicated_pk('tbl_2'); -- Impor data ke tbl_1 lagi. Data berhasil diimpor. -
-
Penyebab 3: Instans memiliki sumber daya memori yang tidak mencukupi untuk mendukung tugas penulisan volume besar.
Solusi:
-
Gunakan fitur Serverless Computing dari Hologres untuk menjalankan tugas penulisan volume besar. Hologres V2.1.17 dan versi yang lebih baru mendukung Serverless Computing. Anda dapat menggunakan fitur ini untuk impor data offline berskala besar, pekerjaan ETL besar, dan kueri volume besar pada tabel eksternal. Serverless Computing menggunakan sumber daya serverless tambahan untuk menjalankan tugas-tugas ini alih-alih menggunakan sumber daya instans Anda. Pendekatan ini menghilangkan kebutuhan untuk menyediakan sumber daya komputasi tambahan untuk instans Anda. Pendekatan ini secara signifikan meningkatkan stabilitas instans dan mengurangi kemungkinan error OOM. Anda hanya dikenai biaya untuk setiap tugas individual. Untuk informasi selengkapnya, lihat Serverless Computing dan Panduan Serverless Computing.
-
Ikuti metode yang dijelaskan dalam Pemecahan masalah error OOM umum.
-