Data lebih besar

Perkakas bulk import neo4j-admin dan pengenalan APOC untuk muatan besar.

Daftar isi

Muatan data yang melebihi kapasitas kerja LOAD CSV menuntut alat yang berbeda. Topik ini membahas konvensi header berkas CSV untuk alat bulk import (impor massal) neo4j-admin database import full yang menulis database baru secara luring, membandingkannya dengan jalur daring LOAD CSV, dan mengenalkan APOC untuk pengolahan besar pada graf yang berjalan. Contoh daringnya dijalankan pada server Neo4j 2026.10 dengan dataset modul ini.

Batas LOAD CSV#

LOAD CSV memproses setiap baris melalui mesin kueri Cypher, sehingga setiap baris dikenai biaya penguraian, perencanaan, dan transaksi. Biaya per baris tersebut wajar untuk muatan sedang dan pembaruan berkala, karena server tetap hidup selama prosesnya dan datanya masuk melalui jalur kueri yang sama dengan beban sehari-hari. Persoalan muncul pada muatan awal berukuran besar, ketika biaya per baris itu dikeluarkan untuk puluhan juta baris sekaligus dan waktu impornya menjadi tidak praktis.

Untuk kebutuhan itu Neo4j menyediakan neo4j-admin database import full, yaitu impor awal berkecepatan tinggi untuk data yang telah bersih, menuju database yang tidak ada atau kosong. Perintah ini berjalan di luar server, membaca berkas CSV secara langsung, dan menulis berkas penyimpanan database tanpa kueri Cypher. Harga per barisnya karenanya jauh lebih murah dibandingkan dengan LOAD CSV. Konsekuensinya, graf sasaran harus berdiri baru, data sumber telah bersih, dan prosesnya memerlukan waktu henti pada database sasaran.

Konvensi header berkas CSV#

Alat import full membaca format CSV miliknya sendiri, dengan baris pertama berupa baris header yang mendefinisikan kolom dalam bentuk <nama>:<tipe>, sedangkan baris berikutnya adalah data, dan kolom properti tanpa tipe dibaca sebagai string. Tabel berikut merangkum nama kolom khusus yang dibaca alat ini.

Kolom headerKegunaan
:IDIdentitas unik node untuk merangkai relasi, dan nama kolomnya menjadi properti
:LABELLabel node, beberapa label dipisahkan karakter ;
:TYPETipe relasi, wajib pada setiap baris berkas relasi
:START_IDIdentitas node awal relasi
:END_IDIdentitas node akhir relasi

Nilai kolom :ID dianggap unik di seluruh berkas node, sedangkan kunci utama basis data relasional hanya unik dalam tabelnya sendiri. Keadaan itu ditangani ID space, yaitu ruang nama identitas yang dideklarasikan pada :ID(Nama) dan dirujuk melalui START_ID(Nama) serta END_ID(Nama). Dataset modul ini memuat pelanggan dan barang dengan nilai id yang bertabrakan, sehingga setiap berkasnya menggunakan ID space sendiri.

Lima berkas berikut menyiapkan ulang dataset modul ini, yaitu tiga berkas node dan dua berkas relasi. Kolom jumlah:int pada relasi-memuat.csv menjadi properti relasi :MEMUAT.

csv nodes-pelanggan.csv
id:ID(Pelanggan),nama,:LABEL
1,Sanggar Cempaka,Pelanggan
2,Koperasi Pena,Pelanggan
3,Studio Angin,Pelanggan
csv nodes-itemtoko.csv
id:ID(ItemToko),nama,:LABEL
1,Buku Ajar Graf,ItemToko
2,Kalender Meja,ItemToko
3,Kertas Gambar A3,ItemToko
csv nodes-pesanan.csv
nomor:ID(Pesanan),:LABEL
1001,Pesanan
1002,Pesanan
1003,Pesanan
1004,Pesanan
csv relasi-memesan.csv
:START_ID(Pesanan),:END_ID(Pelanggan),:TYPE
1001,1,MEMESAN
1002,1,MEMESAN
1003,2,MEMESAN
1004,3,MEMESAN
csv relasi-memuat.csv
:START_ID(Pesanan),jumlah:int,:END_ID(ItemToko),:TYPE
1001,2,1,MEMUAT
1001,1,3,MEMUAT
1002,3,2,MEMUAT
1003,1,1,MEMUAT
1003,2,3,MEMUAT
1004,1,2,MEMUAT

Isi kedua berkas contoh diperiksa dari terminal.

bash
# menampilkan berkas node dan berkas relasi dari terminal
head nodes-pelanggan.csv relasi-memuat.csv
text Keluaran
==> nodes-pelanggan.csv <==
id:ID(Pelanggan),nama,:LABEL
1,Sanggar Cempaka,Pelanggan
2,Koperasi Pena,Pelanggan
3,Studio Angin,Pelanggan

==> relasi-memuat.csv <==
:START_ID(Pesanan),jumlah:int,:END_ID(ItemToko),:TYPE
1001,2,1,MEMUAT
1001,1,3,MEMUAT
1002,3,2,MEMUAT
1003,1,1,MEMUAT
1003,2,3,MEMUAT
1004,1,2,MEMUAT

Menjalankan import full#

Seluruh berkas CSV diletakkan pada folder import instalasi, dan perintah dijalankan dari direktori utama instalasi, sebagaimana contoh dokumentasi yang menggunakan $NEO4J_HOME sebagai direktori kerja. Nama database sasaran dituliskan lebih dahulu, kemudian setiap berkas dirujuk melalui opsi --nodes dan --relationships.

bash
# tidak-dijalankan
# import full berjalan di luar server dan menuntut database sasaran yang tidak ada atau kosong
bin/neo4j-admin database import full graf-toko \
  --nodes=import/nodes-pelanggan.csv \
  --nodes=import/nodes-itemtoko.csv \
  --nodes=import/nodes-pesanan.csv \
  --relationships=import/relasi-memesan.csv \
  --relationships=import/relasi-memuat.csv

Perintah di atas menghasilkan database graf-toko berisi tiga node :Pelanggan, tiga node :ItemToko, empat node :Pesanan, empat relasi :MEMESAN, dan enam relasi :MEMUAT. Database baru tidak dibuat oleh perintah impor, sehingga CREATE DATABASE graf-toko perlu dijalankan setelahnya. Sebelum impor sesungguhnya, opsi --dry-run memeriksa argumen dan memperkirakan ukuran impor tanpa menulis data. Halaman dokumentasi full import menampilkan contoh keluaran mode ini dengan berkas contoh movies dan actors miliknya.

text Keluaran yang diharapkan
Neo4j version: 2026.10.1
Checking the contents of the following files:
Nodes:
  /path/to/neo4j-enterprise-2026.10.1/import/movies_header.csv
  /path/to/neo4j-enterprise-2026.10.1/import/movies.csv
  /path/to/neo4j-enterprise-2026.10.1/import/actors_header.csv
  /path/to/neo4j-enterprise-2026.10.1/import/actors.csv

Relationships:
  null:
  /path/to/neo4j-enterprise-2026.10.1/import/roles_header.csv
  /path/to/neo4j-enterprise-2026.10.1/import/roles.csv

Available resources:
  Total machine memory: 32.00GiB
  Free machine memory: 81.34MiB
  Max heap memory : 7.111GiB
  Max worker threads: 10
  Configured max memory: 88.11MiB
  High parallel IO: true

Cypher type normalization is enabled (disable with --normalize-types=false):
  Property type of 'year' normalized from 'int' --> 'long' in /path/to/neo4j-enterprise-2026.10.1/import/movies_header.csv
Estimated entity counts / sizes:
  Nodes: 6
    Labels: 8
    Total property count: 15
    Total properties size: 237B
  Relationships: 9
    Total property count: 9
    Total properties size: 108B

Keluaran tersebut memuat daftar berkas yang diperiksa, kondisi memori, normalisasi tipe, dan estimasi jumlah entitasnya.

Impor daring pada graf hidup#

Jalur LOAD CSV tetap digunakan ketika graf sudah hidup dan datanya datang bertahap. Contoh berikut menambahkan tiga pegawai baru ke graf modul ini sementara server terus melayani kueri. Pola MERGE berkunci nama digunakan kembali, sehingga kueri yang sama aman dijalankan ulang tanpa menimbulkan node ganda, dan struktur berkasnya mengikuti berkas pegawai modul ini dengan tiga baris tambahan. Berkas berikut diletakkan pada direktori kerja, kemudian salinannya dikirim ke folder import server.

csv karyawan-tambahan.csv
nama,divisi,tahunMasuk
Fajar,Infra,2023
Gita,Data,2023
Hana,Produk,2024
bash
# tidak-dijalankan
# salin berkas CSV ke folder import milik instalasi Neo4j
cp karyawan-tambahan.csv "$NEO4J_HOME"/import/

Kueri pertama menulis node pegawai, dan pemeriksaannya menyaring tiga nama pada berkas agar keluaran hanya menampilkan muatan yang baru diimpor.

cypher
LOAD CSV WITH HEADERS FROM 'file:///karyawan-tambahan.csv' AS baris
MERGE (k:Karyawan {nama: baris.nama})
SET k.divisi = baris.divisi,
    k.tahunMasuk = toInteger(baris.tahunMasuk);
MATCH (k:Karyawan)
WHERE k.nama IN ['Fajar', 'Gita', 'Hana']
RETURN k.nama AS nama, k.divisi AS divisi, k.tahunMasuk AS tahunMasuk
ORDER BY k.nama;
text Keluaran
nama, divisi, tahunMasuk
"Fajar", "Infra", 2023
"Gita", "Data", 2023
"Hana", "Produk", 2024

Keluaran hanya menampilkan muatan baru itu, dengan properti tahunMasuk yang tampil tanpa kutip karena telah dikonversi menjadi bilangan bulat. Relasi ke divisi dibentuk pada kueri kedua dengan mengikat node karyawan dan node divisinya melalui MATCH terlebih dahulu.

cypher
LOAD CSV WITH HEADERS FROM 'file:///karyawan-tambahan.csv' AS baris
MATCH (k:Karyawan {nama: baris.nama})
MATCH (d:Divisi {nama: baris.divisi})
MERGE (k)-[:ANGGOTA_DARI]->(d);
MATCH (k:Karyawan)-[:ANGGOTA_DARI]->(d:Divisi)
WHERE k.nama IN ['Fajar', 'Gita', 'Hana']
RETURN k.nama AS nama, d.nama AS divisi
ORDER BY k.nama;
text Keluaran
nama, divisi
"Fajar", "Infra"
"Gita", "Data"
"Hana", "Produk"

Keluaran kedua memastikan ketiga relasi :ANGGOTA_DARI terbentuk dengan mengikat node karyawan baru ke node :Divisi yang telah berada di dalam graf, semuanya tanpa menghentikan layanan server.

Perbandingan LOAD CSV dan import full#

Kedua alat saling melengkapi, dan tabel berikut merangkum perbedaannya pada aspek yang menentukan pilihan.

AspekLOAD CSVneo4j-admin database import full
Keadaan serverberjalan dan melayani kueridi luar server, database sasaran tidak digunakan
Mekanismekueri Cypher yang memproses baris demi barispembacaan berkas CSV langsung menjadi berkas database
Graf sasarangraf yang sudah ada, data baru menumpukdatabase yang tidak ada, kosong, atau ditimpa
Pengulanganaman karena pola MERGEtidak idempoten, database lama dihapus oleh --overwrite-destination
Muatan yang wajarkecil hingga sedang, datang bertahapbesar, dikerjakan sekaligus

Import full membangun graf baru dari muatan awal yang besar dan telah bersih, sedangkan LOAD CSV memelihara graf tersebut dengan pembaruan kecil yang datang setelah graf itu melayani kueri. Perbedaan itu menjelaskan syarat datanya, karena import full berhenti pada entri yang bermasalah, sedangkan LOAD CSV dapat memperbaiki baris tertentu dengan kueri susulan.

Pengenalan APOC#

Kebutuhan muatan besar tidak selalu berbentuk impor awal, karena graf yang sudah berjalan juga perlu diolah dalam jumlah besar. APOC adalah pustaka berisi ratusan prosedur dan fungsi yang menambah kemampuan Cypher, dipelihara resmi dalam dua paket, yaitu APOC Core dan APOC Extended. Berkasnya dibawa oleh instalasi Neo4j pada folder labs, dan dipasang dengan memindahkan jar tersebut ke folder plugins lalu menyalakan ulang server, dengan versi APOC yang mengikuti tahun dan bulan versi Neo4j.

bash
# tidak-dijalankan
# memindahkan jar APOC dari folder labs ke folder plugins, lalu menyalakan ulang server
mv "$NEO4J_HOME"/labs/apoc-2026.10.0-core.jar "$NEO4J_HOME"/plugins/
neo4j restart

Prosedur yang relevan untuk muatan besar adalah apoc.periodic.iterate, yang menjalankan pernyataan kedua untuk setiap hasil pernyataan pertama, membagi pekerjaan menjadi kelompok sebesar batchSize, dan mengembalikan jumlah kelompok (batches), baris yang diolah (total), serta durasinya (timeTaken). Contoh dokumentasinya menambahkan label :Actor pada node :Person yang memiliki relasi :ACTED_IN.

cypher
# tidak-dijalankan
CALL apoc.periodic.iterate(
  "MATCH (p:Person) WHERE (p)-[:ACTED_IN]->() RETURN p",
  "SET p:Actor",
  {batchSize:10000, parallel:true})

Sejak Neo4j 2026.04 prosedur tersebut dinyatakan deprecated, dan dokumentasinya mengarahkan pemrosesan paralel pada CALL { … } IN CONCURRENT TRANSACTIONS. Bentuk dasarnya adalah subquery ter-batch yang juga digunakan LOAD CSV, sedangkan APOC tetap relevan untuk utilitas lain.

Kesalahan umum#

Tiga kesalahan berikut paling sering muncul saat topik ini dipraktikkan.

  1. Perintah import full dijalankan padahal database sasarannya sedang digunakan. Perintah ditolak, karena database yang ada hanya dapat ditimpa setelah berhenti dan opsi --overwrite-destination diberikan.
  2. Kolom :ID ditulis tanpa ID space padahal kuncinya hanya unik per tabel. Identitas pelanggan dan barang yang sama-sama bernilai satu tidak lagi terbedakan, sehingga relasi dapat menunjuk node yang keliru. Perbaikannya adalah memberi ruang nama pada setiap berkas node dan merujuknya pada berkas relasi.
  3. Prosedur APOC dipanggil padahal pluginnya belum terpasang. Server menjawab error There is no procedure with the name ... registered, karena jar APOC belum berpindah ke folder plugins atau server belum dinyalakan ulang. Perbaikannya adalah menyelesaikan pemasangan plugin terlebih dahulu.

Ringkasan#

  • LOAD CSV memproses setiap baris melalui mesin kueri Cypher pada graf yang berjalan, sedangkan neo4j-admin database import full menulis database baru secara luring tanpa kueri Cypher.
  • Header berkas import full menggunakan konvensi :ID, :LABEL, :START_ID, :END_ID, dan :TYPE, dengan ID space untuk kunci yang hanya unik per tabel.
  • Database hasil import full dibuat setelahnya dengan CREATE DATABASE, dan database lama hanya dapat ditimpa dengan --overwrite-destination setelah berhenti.
  • APOC dipasang dari folder labs ke plugins, dengan apoc.periodic.iterate sebagai pembagi pembaruan besar yang kini mengarah ke CALL { … } IN CONCURRENT TRANSACTIONS.

Referensi#