PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Menambahkan kunci utama multi-kolom ke tabel dengan 40 juta catatan

Gunakan kolom serial

Rencana Anda adalah menambahkan indeks besar yang tidak perlu untuk 40 juta (!) baris. Dan Anda bahkan tidak yakin itu akan menjadi unik. Saya akan sangat menyarankan untuk menentang rute tindakan itu. Tambahkan serial sebagai gantinya dan selesai dengan itu:

ALTER TABLE tbl ADD COLUMN tbl_id serial PRIMARY KEY;

Itu saja yang perlu Anda lakukan. Sisanya terjadi secara otomatis. Lebih banyak di manual atau dalam jawaban yang terkait erat ini:
Peningkatan otomatis kunci utama PostgreSQL lumpuh di C++
Fungsi SQL peningkatan otomatis

Menambahkan serial kolom adalah operasi satu kali, tapi mahal. Seluruh tabel harus ditulis ulang, memblokir pembaruan selama operasi. Paling baik dilakukan tanpa beban bersamaan di luar jam kerja. Saya mengutip manual di sini :

Karena ini secara efektif menulis ulang seluruh tabel, Anda mungkin juga membuat tabel baru dengan kolom pk serial, menyisipkan semua baris dari tabel lama, membiarkan serial mengisi dengan nilai default dari urutannya, menghapus yang lama dan mengganti nama yang baru. Lebih lanjut dalam jawaban yang terkait erat ini:
Memperbarui baris database tanpa mengunci tabel di PostgreSQL 9.2
Tambahkan kolom baru tanpa tabel kunci?

Pastikan semua pernyataan INSERT Anda memiliki daftar target, agar kolom tambahan tidak membingungkan mereka:

INSERT INTO tbl (col1, col2, ...) VALUES ...

Bukan:

INSERT INTO tbl VALUES ...

Sebuah serial diimplementasikan dengan integer kolom (4 byte).
Sebuah batasan kunci utama diimplementasikan dengan indeks unik dan NOT NULL kendala pada kolom yang terlibat.
Isi indeks disimpan seperti tabel. Penyimpanan fisik tambahan diperlukan secara terpisah. Lebih lanjut tentang penyimpanan fisik dalam jawaban terkait ini:
Menghitung dan menghemat ruang di PostgreSQL

Indeks Anda akan menyertakan 2 cap waktu (2 x 8 byte) ditambah nama file yang panjang termasuk. path (~ 50 byte?) Itu akan membuat indeks sekitar 2,5 GB lebih besar (40M x 60 .. sesuatu byte) dan semua operasi lebih lambat.

Menangani duplikat

Cara menangani "mengimpor duplikat" bergantung pada cara Anda mengimpor data dan bagaimana "duplikat" didefinisikan dengan tepat.

Jika kita berbicara tentang COPY pernyataan, salah satu caranya adalah dengan menggunakan tabel pementasan sementara dan menciutkan duplikat dengan SELECT DISTINCT sederhana atau DISTINCT ON di INSERT perintah:

CREATE TEMP TABLE tbl_tmp AS
SELECT * FROM tbl LIMIT 0;     -- copy structure without data and constraints

COPY tbl_tmp FROM '/path/to/file.csv';

INSERT INTO tbl (col1, col2, col3)
SELECT DISTINCT ON (col1, col2)
       col1, col2, col3 FROM tbl_tmp;

Atau, untuk juga melarang duplikat dengan baris yang sudah ada:

INSERT INTO tbl (col1, col2, col3)
SELECT i.*
FROM  (
   SELECT DISTINCT ON (col1, col2)
          col1, col2, col3
   FROM   tbl_tmp
   ) i
LEFT   JOIN tbl t USING (col1, col2)
WHERE  t.col1 IS NULL;

suhu tabel dijatuhkan di akhir sesi secara otomatis.

Tetapi perbaikan yang tepat adalah dengan menangani akar kesalahan yang menghasilkan duplikat sejak awal.

Pertanyaan awal

1) Anda tidak dapat menambahkan pk sama sekali, jika ada satu duplikat di semua kolom.

2) Saya hanya akan menyentuh database PostgreSQL versi 8.1 dengan tiang lima kaki. Ini sangat kuno, ketinggalan jaman dan tidak efisien, tidak didukung lagi dan mungkin memiliki sejumlah lubang keamanan yang tidak diperbaiki. Situs versi Postgres resmi.
@David sudah menyediakan pernyataan SQL.

3 &4) Pelanggaran kunci duplikat. PostgreSQL melempar kesalahan juga berarti seluruh transaksi dibatalkan. Menangkap itu dalam skrip Perl tidak dapat membuat sisa transaksi berjalan. Anda harus membuat skrip sisi server dengan plpgsql misalnya, di mana Anda dapat menangkap pengecualian.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hibernate + PostgreSQL :relasi tidak ada - SQL Error:0, SQLState:42P01

  2. buat kueri dinamis SQL dengan pustaka python psycopg2 dan menggunakan alat tipe konversi yang baik

  3. Django. PostgreSQL. regexp_split_to_table tidak berfungsi

  4. Indeks `gin_trgm_ops` Postgres tidak digunakan

  5. Pembuatan data dan kualitas perangkat keras