Bagaimana cara memperbarui nilai atribut untuk semua rekaman dalam tabel? Bagaimana cara menambahkan kunci utama atau unik ke tabel? Bagaimana cara membagi tabel menjadi dua? Bagaimana ...
Jika aplikasi mungkin tidak tersedia untuk beberapa waktu untuk migrasi, maka jawaban untuk pertanyaan ini tidaklah sulit. Tetapi bagaimana jika Anda perlu melakukan migrasi panas - tanpa menghentikan database dan tanpa mengganggu orang lain untuk bekerja dengannya?
Kami akan mencoba menjawab ini dan pertanyaan lain yang muncul selama skema dan migrasi data di PostgreSQL dalam bentuk saran praktis.
Artikel ini - kinerja decoding di konferensi SmartDataConf (di sini Anda dapat menemukan presentasi, video akan muncul pada waktunya). Teksnya banyak, jadi materi akan dibagi menjadi 2 artikel:
- migrasi dasar
- pendekatan untuk memperbarui tabel besar.
Di bagian akhir terdapat rangkuman dari keseluruhan artikel berupa contekan tabel pivot.
Kandungan
Inti dari masalah
Tambahkan kolom
Tambahkan kolom default
Hapus kolom
Buat indeks
Buat indeks pada tabel yang dipartisi
Buat batasan NOT NULL
Buat kunci asing
Buat batasan unik
Buat kunci utama Lembar Cheat
Migrasi Cepat
Inti dari masalahnya
Misalkan kita memiliki aplikasi yang bekerja dengan database. Dalam konfigurasi minimal, dapat terdiri dari 2 node - aplikasi itu sendiri dan database, masing-masing.
Dengan skema ini, pembaruan aplikasi sering terjadi dengan waktu henti. Pada saat yang sama, Anda dapat memperbarui database. Dalam situasi seperti itu, kriteria utamanya adalah waktu, yaitu Anda harus menyelesaikan migrasi secepat mungkin untuk meminimalkan waktu tidak tersedianya layanan.
Jika aplikasi berkembang dan menjadi perlu untuk melakukan rilis tanpa waktu henti, kami mulai menggunakan beberapa server aplikasi. Jumlahnya bisa sebanyak yang Anda suka, dan ada dalam versi yang berbeda. Dalam hal ini, penting untuk memastikan kompatibilitas ke belakang.
Pada tahap pertumbuhan berikutnya, data tidak lagi cocok dengan satu database. Kami juga mulai menskalakan database - dengan sharding. Karena dalam praktiknya, sangat sulit untuk memigrasi banyak database secara sinkron, ini berarti bahwa pada titik tertentu mereka akan memiliki skema data yang berbeda. Karenanya, kami akan bekerja di lingkungan yang heterogen, di mana server aplikasi mungkin memiliki kode dan database yang berbeda dengan skema data yang berbeda.
Tentang konfigurasi inilah yang akan kita bicarakan di artikel ini dan mempertimbangkan migrasi paling populer yang ditulis pengembang - dari yang sederhana hingga yang lebih kompleks.
Sasaran kami adalah melakukan migrasi SQL dengan dampak minimal pada kinerja aplikasi, yaitu. ubah data atau skema data agar aplikasi terus berjalan dan pengguna tidak menyadarinya.
Menambahkan kolom
ALTER TABLE my_table ADD COLUMN new_column INTEGER --
Mungkin, setiap orang yang bekerja dengan database menulis migrasi serupa. Jika kita berbicara tentang PostgreSQL, maka migrasi ini sangat murah dan aman. Perintah itu sendiri, meskipun menangkap kunci tingkat tertinggi ( AccessExclusive ), dijalankan dengan sangat cepat, karena di balik terpal hanya ada penambahan informasi meta tentang kolom baru tanpa menulis ulang data tabel itu sendiri. Dalam kebanyakan kasus, ini terjadi tanpa disadari. Tetapi masalah bisa muncul jika pada saat migrasi ada transaksi lama yang bekerja dengan tabel ini. Untuk memahami inti masalahnya, mari kita lihat contoh kecil tentang bagaimana kunci bekerja dengan cara yang disederhanakan di PostgreSQL. Aspek ini akan menjadi sangat penting ketika mempertimbangkan sebagian besar migrasi lainnya.
Misalkan kita memiliki tabel besar dan kita MEMILIH semua data darinya. Bergantung pada ukuran database dan tabel itu sendiri, ini bisa memakan waktu beberapa detik atau bahkan menit.
Kunci AccessShare terlemah yang melindungi terhadap perubahan pada struktur tabel diperoleh selama transaksi .
Saat ini, transaksi lain datang, yang hanya mencoba membuat kueri ALTER TABLE ke tabel ini. Perintah ALTER TABLE, seperti yang disebutkan sebelumnya, mengambil kunci AccessExclusive , yang sama sekali tidak kompatibel dengan kunci lain. Dia mengantre.
Antrian kunci ini "disapu" dalam urutan yang ketat; bahkan jika kueri lain muncul setelah ALTER TABLE (misalnya, juga SELECTs), yang dengan sendirinya tidak bertentangan dengan kueri pertama, mereka semua mengantri untuk ALTER TABLE. Akibatnya, aplikasi "berdiri" dan menunggu ALTER TABLE dijalankan.
Apa yang harus dilakukan dalam situasi seperti ini? Anda dapat membatasi waktu yang diperlukan untuk mendapatkan kunci menggunakan perintah SET lock_timeout . Kami menjalankan perintah ini sebelum ALTER TABLE (kata kunci LOKAL berarti bahwa pengaturan hanya valid dalam transaksi saat ini, jika tidak - dalam sesi saat ini):
SET LOCAL lock_timeout TO '100ms'
dan jika dalam 100 milidetik perintah gagal mendapatkan kunci, itu akan gagal. Kemudian kami memulainya lagi, mengharapkannya berhasil, atau kami mencari tahu mengapa transaksi membutuhkan waktu lama, jika ini tidak seharusnya ada dalam aplikasi kami. Bagaimanapun, yang utama adalah kami tidak merusak aplikasi.
Harus dikatakan bahwa menyetel batas waktu berguna sebelum perintah apa pun yang mengambil kunci ketat.
Menambahkan kolom dengan nilai default
-- PG 11
ALTER TABLE my_table ADD COLUMN new_column INTEGER DEFAULT 42
Jika perintah ini dijalankan di versi PostgreSQL yang lebih lama (di bawah 11), maka itu akan menimpa semua baris di tabel. Tentunya, jika mejanya besar, ini bisa memakan waktu lama. Dan karena kunci ketat ( AccessExclusive ) ditangkap untuk waktu eksekusi , semua kueri ke tabel juga diblokir.
Jika PostgreSQL 11 atau lebih baru, operasi ini cukup murah. Faktanya adalah bahwa dalam versi ke-11 pengoptimalan telah dilakukan, berkat itu, alih-alih menulis ulang tabel, nilai default disimpan dalam tabel khusus pg_attribute, dan kemudian, saat melakukan PILIH, semua nilai kosong dari kolom ini akan diganti dengan cepat dengan nilai ini. Dalam kasus ini, nanti, saat baris dalam tabel ditimpa karena modifikasi lain, nilainya akan ditulis ke baris ini.
Selain itu, dari versi ke 11, Anda juga dapat langsung membuat kolom baru dan menandainya sebagai NOT NULL:
-- PG 11
ALTER TABLE my_table ADD COLUMN new_column INTEGER DEFAULT 42 NOT NULL
Bagaimana jika PostgreSQL lebih tua dari 11?
Migrasi dapat dilakukan dalam beberapa langkah. Pertama, kami membuat kolom baru tanpa batasan dan nilai default. Seperti yang dinyatakan sebelumnya, harganya murah dan cepat. Dalam transaksi yang sama, kami memodifikasi kolom ini dengan menambahkan nilai default.
ALTER TABLE my_table ADD COLUMN new_column INTEGER;
ALTER TABLE my_table ALTER COLUMN new_column SET DEFAULT 42;
Pembagian satu perintah menjadi dua ini mungkin tampak sedikit aneh, tetapi mekanismenya sedemikian rupa sehingga ketika kolom baru dibuat segera dengan nilai default, itu mempengaruhi semua catatan yang ada dalam tabel, dan ketika nilai ditetapkan untuk kolom yang ada (bahkan jika hanya apa yang dibuat, seperti dalam kasus kami), itu hanya mempengaruhi rekaman baru.
Jadi, setelah menjalankan perintah-perintah ini, kita tetap harus memperbarui nilai yang sudah ada di tabel. Secara kasar, kita perlu melakukan sesuatu seperti ini:
UPDATE my_table set new_column = 42 --
Tetapi UPDATE "head-on" seperti itu sebenarnya tidak mungkin, karena saat memperbarui tabel besar, kita akan mengunci seluruh tabel untuk waktu yang lama. Di artikel kedua (di sini di masa mendatang akan ada tautan) kita akan melihat strategi apa yang ada untuk memperbarui tabel besar di PostgreSQL, tetapi untuk saat ini kita akan berasumsi bahwa kita telah memperbarui datanya, dan sekarang baik data lama dan yang baru akan dengan nilai yang diperlukan secara default.
Menghapus kolom
ALTER TABLE my_table DROP COLUMN new_column --
Di sini logikanya sama seperti saat menambahkan kolom: data tabel tidak diubah, hanya informasi meta yang diubah. Dalam kasus ini, kolom ditandai sebagai dihapus dan tidak tersedia untuk kueri. Ini menjelaskan fakta bahwa ketika kolom dijatuhkan di PostgreSQL, tidak ada ruang fisik yang dibebaskan (kecuali Anda melakukan VACUUM FULL), yaitu, data catatan lama masih tetap ada di tabel, tetapi tidak tersedia saat diakses. Deallokasi terjadi secara bertahap saat baris dalam tabel ditimpa.
Jadi, migrasi itu sendiri sederhana, tetapi, sebagai aturan, kesalahan terkadang ditemui di sisi backend. Sebelum menghapus kolom, ada beberapa langkah persiapan sederhana yang harus dilakukan.
- Pertama, Anda perlu menghapus semua batasan (NOT NULL, CHECK, ...) yang ada di kolom ini:
ALTER TABLE my_table ALTER COLUMN new_column DROP NOT NULL
- Langkah selanjutnya adalah memastikan kompatibilitas backend. Anda perlu memastikan bahwa kolom tersebut tidak digunakan di mana pun. Misalnya, dalam mode Hibernate, Anda perlu menandai bidang menggunakan anotasi
@Transient
. Di JOOQ yang kami gunakan, bidang ditambahkan ke pengecualian menggunakan tag<excludes>
:
<excludes>my_table.new_column</excludes>
Anda juga perlu melihat lebih dekat pada kueri"SELECT *"
- kerangka kerja dapat memetakan semua kolom ke dalam struktur dalam kode (dan sebaliknya) dan, karenanya, Anda mungkin lagi menghadapi masalah mengakses kolom yang tidak ada.
Setelah perubahan dikirim ke semua server aplikasi, Anda dapat menghapus kolom tersebut.
Pembuatan indeks
CREATE INDEX my_table_index ON my_table (name) -- ,
Mereka yang bekerja dengan PostgreSQL mungkin tahu bahwa perintah ini mengunci seluruh tabel. Tetapi karena versi 8.2 yang sangat lama ada kata kunci SECARA SAMPAI , yang memungkinkan Anda membuat indeks dalam mode non-pemblokiran.
CREATE CONCURRENTLY INDEX my_table_index ON my_table (name) --
Perintahnya lebih lambat, tetapi tidak mengganggu permintaan paralel.
Tim ini memiliki satu peringatan. Itu bisa gagal - misalnya, saat membuat indeks unik pada tabel yang berisi nilai duplikat. Indeks akan dibuat, tetapi akan ditandai sebagai tidak valid dan tidak akan digunakan dalam kueri. Status indeks dapat diperiksa dengan query berikut:
SELECT pg_index.indisvalid
FROM pg_class, pg_index
WHERE pg_index.indexrelid = pg_class.oid
AND pg_class.relname = 'my_table_index'
Dalam situasi seperti ini, Anda perlu menghapus indeks lama, mengoreksi nilai dalam tabel, lalu membuatnya kembali.
DROP INDEX CONCURRENTLY my_table_index
UPDATE my_table ...
CREATE CONCURRENTLY INDEX my_table_index ON my_table (name)
Penting untuk dicatat bahwa perintah REINDEX , yang hanya dimaksudkan untuk membangun kembali indeks, hanya berfungsi dalam mode pemblokiran hingga versi 12 , yang membuatnya tidak mungkin untuk digunakan. PostgreSQL 12 menambahkan dukungan SECARA KONSUREN dan sekarang dapat digunakan.
REINDEX INDEX CONCURRENTLY my_table_index -- PG 12
Membuat Indeks pada Tabel yang Dipartisi
Kita juga harus membahas pembuatan indeks untuk tabel yang dipartisi. Di PostgreSQL, ada 2 jenis partisi: melalui warisan dan deklaratif, yang muncul di versi 10. Mari kita lihat keduanya dengan contoh sederhana.
Misalkan kita ingin mempartisi tabel berdasarkan tanggal, dan setiap partisi akan berisi data selama satu tahun.
Saat mempartisi melalui warisan, kita akan memiliki kira-kira skema berikut.
Tabel induk:
CREATE TABLE my_table (
...
reg_date date not null
)
Partisi anak untuk tahun 2020 dan 2021:
CREATE TABLE my_table_y2020 (
CHECK ( reg_date >= DATE '2020-01-01' AND reg_date < DATE '2021-01-01' ))
INHERITS (my_table);
CREATE TABLE my_table_y2021 (
CHECK ( reg_date >= DATE '2021-01-01' AND reg_date < DATE '2022-01-01' ))
INHERITS (my_table);
Indeks menurut bidang partisi untuk setiap partisi:
CREATE INDEX ON my_table_y2020 (reg_date);
CREATE INDEX ON my_table_y2021 (reg_date);
Mari kita tinggalkan pembuatan pemicu / aturan untuk memasukkan data ke dalam tabel.
Hal terpenting di sini adalah bahwa setiap partisi praktis merupakan tabel independen yang dikelola secara terpisah. Jadi, membuat indeks baru juga dilakukan seperti tabel biasa:
CREATE CONCURRENTLY INDEX my_table_y2020_index ON my_table_y2020 (name);
CREATE CONCURRENTLY INDEX my_table_y2021_index ON my_table_y2021 (name);
Sekarang mari kita lihat partisi deklaratif.
CREATE TABLE my_table (...) PARTITION BY RANGE (reg_date);
CREATE TABLE my_table_y2020 PARTITION OF my_table FOR VALUES FROM ('2020-01-01') TO ('2020-12-31');
CREATE TABLE my_table_y2021 PARTITION OF my_table FOR VALUES FROM ('2021-01-01') TO ('2021-12-31');
Pembuatan indeks tergantung pada versi PostgreSQL. Di versi 10, indeks dibuat secara terpisah - seperti dalam pendekatan sebelumnya. Karenanya, membuat indeks baru untuk tabel yang sudah ada juga dilakukan dengan cara yang sama.
Di versi 11, partisi deklaratif telah ditingkatkan dan tabel sekarang disajikan bersama . Membuat indeks pada tabel induk secara otomatis membuat indeks untuk semua partisi yang ada dan baru yang akan dibuat di masa mendatang:
-- PG 11 ()
CREATE INDEX ON my_table (reg_date)
Ini berguna saat membuat tabel yang dipartisi, tetapi tidak saat membuat indeks baru pada tabel yang sudah ada, karena perintah tersebut mengambil kunci yang kuat saat indeks dibuat.
CREATE INDEX ON my_table (name) --
Sayangnya, BUAT INDEKS tidak mendukung kata kunci SECARA SESAMA untuk tabel yang dipartisi. Untuk menyiasati batasan dan bermigrasi tanpa memblokir, Anda dapat melakukan hal berikut.
- Buat indeks pada tabel induk dengan opsi HANYA
CREATE INDEX my_table_index ON ONLY my_table (name)
Perintah tersebut akan membuat indeks kosong yang tidak valid tanpa membuat indeks untuk partisi . - Buat indeks untuk setiap partisi:
CREATE CONCURRENTLY INDEX my_table_y2020_index ON my_table_y2020 (name); CREATE CONCURRENTLY INDEX my_table_y2021_index ON my_table_y2021 (name);
- Lampirkan indeks partisi ke indeks tabel induk:
Setelah semua indeks dilampirkan, indeks tabel induk secara otomatis menjadi valid.ALTER INDEX my_table_index ATTACH PARTITION my_table_y2020_index; ALTER INDEX my_table_index ATTACH PARTITION my_table_y2021_index;
Batasan
Sekarang mari kita bahas batasan: NOT NULL, foreign, unique dan primary key.
Membuat batasan NOT NULL
ALTER TABLE my_table ALTER COLUMN name SET NOT NULL --
Membuat batasan dengan cara ini akan memindai seluruh tabel - semua baris akan diperiksa untuk kondisi bukan null, dan jika tabel besar, mungkin perlu waktu lama. Blok kuat yang ditangkap oleh perintah ini akan memblokir semua permintaan bersamaan hingga selesai.
Apa yang bisa dilakukan? PostgreSQL memiliki jenis kendala lain, PERIKSA , yang dapat digunakan untuk mendapatkan hasil yang diinginkan. Batasan ini menguji kondisi boolean apa pun yang terdiri dari kolom baris. Dalam kasus kami, kondisinya sepele -
CHECK (name IS NOT NULL)
. Tetapi yang paling penting, batasan PERIKSA mendukung pembatalan (kata kunci
NOT VALID
):
ALTER TABLE my_table ADD CONSTRAINT chk_name_not_null
CHECK (name IS NOT NULL) NOT VALID -- , PG 9.2
Batasan yang dibuat dengan cara ini hanya berlaku untuk rekaman yang baru ditambahkan dan diubah, dan yang sudah ada tidak dicentang, sehingga tabel tidak dipindai.
Untuk memastikan bahwa record yang ada juga memenuhi batasan tersebut, maka perlu dilakukan validasi (tentu saja dengan mengupdate data di tabel terlebih dahulu):
ALTER TABLE my_table VALIDATE CONSTRAINT chk_name_not_null
Perintah iterasi di atas baris tabel dan memeriksa bahwa semua record bukan null. Tetapi tidak seperti batasan NOT NULL yang biasa, kunci yang ditangkap dalam perintah ini tidak sekuat (ShareUpdateExclusive) - tidak memblokir operasi penyisipan, pembaruan, dan penghapusan.
Membuat kunci asing
ALTER TABLE my_table ADD CONSTRAINT fk_group
FOREIGN KEY (group_id) REFERENCES groups(id) --
Saat kunci asing ditambahkan, semua rekaman di tabel anak diperiksa untuk nilai di induk. Jika meja besar, maka pemindaian ini akan panjang, dan kunci yang dipegang pada kedua tabel juga akan panjang.
Untungnya, foreign key di PostgreSQL juga mendukung NOT VALID, yang berarti kita dapat menggunakan pendekatan yang sama seperti yang dibahas sebelumnya dengan CHECK. Mari buat kunci asing yang tidak valid:
ALTER TABLE my_table ADD CONSTRAINT fk_group
FOREIGN KEY (group_id) REFERENCES groups(id) NOT VALID
kemudian kami memperbarui data dan melakukan validasi:
ALTER TABLE my_table VALIDATE CONSTRAINT fk_group_id
Buat batasan unik
ALTER TABLE my_table ADD CONSTRAINT uk_my_table UNIQUE (id) --
Seperti dalam kasus dengan batasan yang telah dibahas sebelumnya, perintah menangkap kunci yang ketat, di mana perintah tersebut memeriksa semua baris dalam tabel terhadap batasan - dalam hal ini, keunikan.
Penting untuk diketahui bahwa di balik terpal PostgreSQL menerapkan batasan unik menggunakan indeks unik. Dengan kata lain, ketika batasan dibuat, indeks unik yang sesuai dengan nama yang sama dibuat untuk melayani batasan itu. Dengan menggunakan kueri berikut, Anda dapat mengetahui indeks penyajian dari batasan:
SELECT conindid index_oid, conindid::regclass index_name
FROM pg_constraint
WHERE conname = 'uk_my_table_id'
Pada saat yang sama digunakan pada sebagian besar batasan waktu untuk membuat hal yang sama berlaku untuk indeks, dan pengikatan berikutnya untuk membatasi dengan sangat cepat. Selain itu, jika Anda sudah membuat indeks unik, Anda dapat melakukannya sendiri dengan membuat indeks menggunakan kata kunci USING INDEX:
ALTER TABLE my_table ADD CONSTRAINT uk_my_table_id UNIQUE
USING INDEX uk_my_table_id -- , PG 9.1
Jadi, idenya sederhana - kita membuat indeks unik SECARA SEKARANG, seperti yang kita bahas sebelumnya, dan kemudian membuat batasan unik berdasarkan itu.
Pada titik ini, pertanyaan yang mungkin timbul - mengapa membuat batasan sama sekali, jika indeks melakukan apa yang diperlukan - menjamin keunikan nilai? Jika kita mengecualikan indeks parsial dari perbandingan , maka dari sudut pandang fungsional, hasilnya hampir sama. Satu-satunya perbedaan yang kami temukan adalah bahwa batasan dapat ditangguhkan , tetapi indeks tidak bisa. Dokumentasi untuk versi lama PostgreSQL (hingga dan termasuk 9.4) memiliki catatan kakidengan informasi bahwa cara yang disukai untuk membuat batasan keunikan adalah secara eksplisit membuat batasan
ALTER TABLE ... ADD CONSTRAINT
, dan penggunaan indeks harus dianggap sebagai detail implementasi. Namun, di versi yang lebih baru, catatan kaki ini telah dihapus.
Membuat kunci utama
Selain unik, kunci utama memberlakukan batasan bukan nol. Jika kolom awalnya memiliki batasan seperti itu, maka tidak akan sulit untuk "mengubahnya" menjadi kunci utama - kami juga membuat indeks unik SECARA SEKARANG, lalu kunci utama:
ALTER TABLE my_table ADD CONSTRAINT uk_my_table_id PRIMARY KEY
USING INDEX uk_my_table_id -- id is NOT NULL
Penting untuk dicatat bahwa kolom harus memiliki batasan NOT NULL yang "adil" - pendekatan CHECK yang telah dibahas sebelumnya tidak akan berfungsi.
Jika tidak ada batasan, maka hingga versi ke-11 dari PostgreSQL tidak ada yang bisa dilakukan - tidak ada cara untuk membuat kunci utama tanpa penguncian.
Jika Anda memiliki PostgreSQL 11 atau yang lebih baru, ini dapat dilakukan dengan membuat kolom baru yang akan menggantikan yang sudah ada. Jadi, selangkah demi selangkah.
Buat kolom baru yang bukan null secara default dan memiliki nilai default:
ALTER TABLE my_table ADD COLUMN new_id INTEGER NOT NULL DEFAULT -1 -- PG 11
Kami menyiapkan sinkronisasi data kolom lama dan baru menggunakan pemicu:
CREATE FUNCTION on_insert_or_update() RETURNS TRIGGER AS
$$
BEGIN
NEW.new_id = NEW.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg BEFORE INSERT OR UPDATE ON my_table
FOR EACH ROW EXECUTE PROCEDURE on_insert_or_update();
Selanjutnya, Anda perlu memperbarui data untuk baris yang tidak terpengaruh oleh pemicu:
UPDATE my_table SET new_id = id WHERE new_id = -1 --
Permintaan dengan pembaruan di atas ditulis "di dahi", di atas meja besar tidak ada gunanya, karena akan ada pemblokiran yang lama. Seperti disebutkan sebelumnya, artikel kedua akan membahas pendekatan untuk memperbarui tabel besar. Untuk saat ini, anggap saja data diperbarui dan yang tersisa hanyalah menukar kolom.
ALTER TABLE my_table RENAME COLUMN id TO old_id;
ALTER TABLE my_table RENAME COLUMN new_id TO id;
ALTER TABLE my_table RENAME COLUMN old_id TO new_id;
Di PostgreSQL, perintah DDL bersifat transaksional - ini berarti Anda dapat mengganti nama, menambah, menghapus kolom, dan pada saat yang sama transaksi paralel tidak akan melihatnya selama operasinya.
Setelah mengubah kolom, tetap membuat indeks dan "membersihkan" - hapus pemicu, fungsi dan kolom lama.
Lembar contekan cepat dengan migrasi
Sebelum perintah apa pun yang menangkap kunci kuat (hampir semua
ALTER TABLE ...
), disarankan untuk memanggil:
SET LOCAL lock_timeout TO '100ms'
| Migrasi | Pendekatan yang direkomendasikan |
|---|---|
| Menambahkan kolom | |
| Menambahkan kolom dengan nilai default [dan NOT NULL] | dengan PostgreSQL 11:
sebelum PostgreSQL 11:
|
| Menghapus kolom |
|
| Pembuatan indeks |
Jika gagal:
|
| Membuat Indeks pada Tabel yang Dipartisi | Mempartisi melalui pewarisan + deklaratif di PG 10:
Partisi Deklaratif dengan PG 11:
|
| Membuat batasan NOT NULL |
|
| Membuat kunci asing |
|
| Buat batasan unik |
|
| Membuat kunci utama | Jika kolom IS NOT NULL:
Jika kolom IS NULL dengan PG 11:
|
Di artikel berikutnya, kita akan melihat pendekatan untuk memperbarui tabel besar.
Migrasi mudah semuanya!