Kami mulai dengan masalah yang berkaitan dengan
isolasi , melakukan penyimpangan tentang
pengorganisasian data pada tingkat rendah , kemudian berbicara secara rinci
tentang versi baris dan bagaimana
snapshots diperoleh dari versi.
Terakhir kali kami berbicara tentang pembaruan-HOT dan pembersihan dalam-halaman, dan hari ini kita akan melihat pembersihan biasa,
vakum vulgaris yang terkenal . Ya, sudah banyak yang ditulis tentang dia sehingga saya tidak mungkin mengatakan sesuatu yang baru, tetapi kelengkapan gambar membutuhkan pengorbanan. Bersabarlah.
Pembersihan normal (vakum)
Apa yang dilakukan pembersihan
Pembersihan intra-halaman cepat, tetapi hanya membebaskan sebagian kecil dari ruang. Ini berfungsi dalam halaman tabular yang sama dan tidak memengaruhi indeks.
Pembersihan utama, "normal" dilakukan oleh perintah VACUUM dan kami akan menyebutnya hanya pembersihan (dan kami akan berbicara tentang pembersihan otomatis secara terpisah).
Jadi, proses pembersihan tabel sepenuhnya. Ini membersihkan tidak hanya versi string yang tidak perlu, tetapi juga referensi untuk mereka dari semua indeks.
Pemrosesan terjadi secara paralel dengan aktivitas lain dalam sistem. Dalam hal ini, tabel dan indeks dapat digunakan dengan cara biasa baik untuk membaca dan untuk mengubah (namun, eksekusi perintah secara bersamaan seperti CREATE INDEX, ALTER TABLE dan beberapa lainnya tidak akan mungkin).
Hanya halaman-halaman di mana beberapa aktivitas terjadi dilihat dalam tabel. Untuk ini, peta visibilitas digunakan (saya ingatkan Anda bahwa halaman yang hanya berisi versi baris yang cukup lama yang dijamin akan terlihat di semua snapshot data ditandai di dalamnya). Hanya halaman yang tidak ditandai pada peta yang diproses, sementara peta itu sendiri diperbarui.
Dalam prosesnya, peta ruang bebas diperbarui untuk mencerminkan ruang kosong yang muncul di halaman.
Seperti biasa, buat tabel:
=> CREATE TABLE vac( id serial, s char(100) ) WITH (autovacuum_enabled = off); => CREATE INDEX vac_s ON vac(s); => INSERT INTO vac(s) VALUES ('A'); => UPDATE vac SET s = 'B'; => UPDATE vac SET s = 'C';
Menggunakan parameter
autovacuum_enabled, kami mematikan pembersihan otomatis. Kami akan membicarakannya lain kali, tetapi untuk sekarang - untuk eksperimen - penting bagi kami untuk mengelola pembersihan secara manual.
Ada tiga versi baris dalam tabel sekarang, dan masing-masing ditautkan dari indeks:
=> SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+----------+-----+-----+-------- (0,1) | normal | 4000 (c) | 4001 (c) | | | (0,2) (0,2) | normal | 4001 (c) | 4002 | | | (0,3) (0,3) | normal | 4002 | 0 (a) | | | (0,3) (3 rows)
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,1) 2 | (0,2) 3 | (0,3) (3 rows)
Setelah dibersihkan, versi "mati" menghilang dan hanya ada satu yang relevan. Dan indeks juga memiliki satu tautan tersisa:
=> VACUUM vac; => SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+-------+-----+-----+-------- (0,1) | unused | | | | | (0,2) | unused | | | | | (0,3) | normal | 4002 (c) | 0 (a) | | | (0,3) (3 rows)
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,3) (1 row)
Harap dicatat bahwa dua petunjuk pertama menerima status yang tidak digunakan, dan tidak mati, seperti halnya dengan pembersihan dalam halaman.
Dan lagi tentang cakrawala transaksi
Bagaimana PostgreSQL menentukan versi baris mana yang dapat dianggap โmatiโ? Kami sudah mempertimbangkan konsep cakrawala transaksi ketika kami berbicara
tentang snapshot
data , tetapi ini adalah topik yang sangat penting sehingga bukan dosa untuk mengulanginya.
Mari kita mulai pengalaman sebelumnya lagi.
=> TRUNCATE vac; => INSERT INTO vac(s) VALUES ('A'); => UPDATE vac SET s = 'B';
Tetapi sebelum memperbarui saluran lagi, biarkan transaksi lain dimulai (tetapi tidak berakhir). Dalam contoh kami, ini akan bekerja di tingkat Komitmen Baca, tetapi harus mendapatkan nomor transaksi nyata (non-virtual). Sebagai contoh, ini dapat mengubah atau bahkan hanya mengunci beberapa baris di tabel apa pun, tidak harus dalam kondisi vakum:
| => BEGIN; | => SELECT s FROM t FOR UPDATE;
| s | ----- | FOO | BAR | (2 rows)
=> UPDATE vac SET s = 'C';
Ada tiga baris dalam tabel, dan tiga tautan dalam indeks. Apa yang terjadi setelah dibersihkan?
=> VACUUM vac; => SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+----------+-----+-----+-------- (0,1) | unused | | | | | (0,2) | normal | 4005 (c) | 4007 (c) | | | (0,3) (0,3) | normal | 4007 (c) | 0 (a) | | | (0,3) (3 rows)
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,2) 2 | (0,3) (2 rows)
Ada dua versi baris yang tersisa di tabel: pembersihan memutuskan bahwa versi (0,2) belum dapat dihapus. Alasannya, tentu saja, adalah di cakrawala transaksi basis data, yang dalam contoh kita ditentukan oleh transaksi yang tidak lengkap:
| => SELECT backend_xmin FROM pg_stat_activity WHERE pid = pg_backend_pid();
| backend_xmin | -------------- | 4006 | (1 row)
Anda dapat meminta pembersihan untuk membicarakan apa yang terjadi:
=> VACUUM VERBOSE vac;
INFO: vacuuming "public.vac" INFO: index "vac_s" now contains 2 row versions in 2 pages DETAIL: 0 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: "vac": found 0 removable, 2 nonremovable row versions in 1 out of 1 pages DETAIL: 1 dead row versions cannot be removed yet, oldest xmin: 4006 There were 1 unused item pointers. Skipped 0 pages due to buffer pins, 0 frozen pages. 0 pages are entirely empty. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. VACUUM
Harap dicatat:
- 2 versi baris yang tidak dapat dihapus - 2 versi ditemukan dalam tabel yang tidak dapat dihapus,
- 1 versi baris mati belum dapat dihapus - termasuk 1 "mati",
- xmin terlama menunjukkan cakrawala saat ini.
Kami mengulangi kesimpulan sekali lagi: keberadaan transaksi jangka panjang dalam database (tidak selesai atau berjalan sangat lama) dapat menyebabkan perluasan tabel (mengasapi), terlepas dari seberapa sering pembersihan dilakukan. Oleh karena itu, dalam PostgreSQL, beban kerja OLTP dan OLAP buruk dikombinasikan dalam satu database: laporan yang berjalan berjam-jam tidak akan memungkinkan tabel yang sering diperbarui untuk dihapus tepat waktu. Solusi yang mungkin adalah membuat replika "pelaporan" yang terpisah.
Setelah penyelesaian transaksi terbuka, cakrawala bergeser dan situasinya diperbaiki:
| => COMMIT;
=> VACUUM VERBOSE vac;
INFO: vacuuming "public.vac" INFO: scanned index "vac_s" to remove 1 row versions DETAIL: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: "vac": removed 1 row versions in 1 pages DETAIL: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: index "vac_s" now contains 1 row versions in 2 pages DETAIL: 1 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: "vac": found 1 removable, 1 nonremovable row versions in 1 out of 1 pages DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4008 There were 1 unused item pointers. Skipped 0 pages due to buffer pins, 0 frozen pages. 0 pages are entirely empty. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. VACUUM
Sekarang halaman hanya memiliki versi terbaru dari baris:
=> SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+-------+-----+-----+-------- (0,1) | unused | | | | | (0,2) | unused | | | | | (0,3) | normal | 4007 (c) | 0 (a) | | | (0,3) (3 rows)
Hanya ada satu entri dalam indeks:
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,3) (1 row)
Apa yang terjadi di dalam
Pembersihan harus memproses tabel dan indeks secara bersamaan, dan melakukannya dengan cara yang tidak menghalangi operasi proses lainnya. Bagaimana dia melakukannya?
Semuanya dimulai dengan
pemindaian tabel (dengan mempertimbangkan peta visibilitas, sebagaimana telah dicatat). Di halaman baca, versi string yang tidak perlu ditentukan dan pengidentifikasi mereka (tid) ditulis ke array khusus. Array terletak di memori lokal dari proses pembersihan; sebuah fragmen ukuran
maintenance_work_mem dialokasikan untuk itu. Nilai default untuk parameter ini adalah 64 MB. Perhatikan bahwa memori ini dialokasikan segera secara penuh, dan tidak sesuai kebutuhan. Benar, jika tabelnya kecil, maka fragmennya dialokasikan lebih sedikit.
Berikutnya, salah satu dari dua hal: kita akan mencapai akhir tabel, atau memori yang dialokasikan untuk array akan berakhir. Dalam salah satu dari dua kasus,
fase pembersihan indeks dimulai. Untuk melakukan ini,
setiap indeks yang dibuat di atas tabel
dipindai sepenuhnya untuk mencari catatan yang mereferensikan versi baris yang tersimpan. Catatan yang ditemukan dihapus dari halaman indeks.
Pada titik ini kita mendapatkan gambar berikut: dalam indeks tidak ada lagi tautan ke versi baris yang tidak perlu, tetapi masih ada dalam tabel. Ini tidak bertentangan dengan apa pun: saat menjalankan kueri, kami tidak mendapatkan versi baris yang mati sama sekali (dengan akses indeks), atau menandainya saat memeriksa visibilitas (saat memindai tabel).
Setelah itu,
fase pembersihan meja dimulai. Tabel dipindai lagi untuk membaca halaman yang diperlukan, untuk menghapus versi yang disimpan dari garis-garis itu, dan untuk membebaskan pointer. Kita dapat melakukan ini karena tidak ada tautan dari indeks lagi.
Jika tabel tidak sepenuhnya dibaca di pass pertama, maka array dihapus dan semuanya diulang dari tempat kami tinggalkan.
Dengan cara ini:
- tabel selalu dipindai dua kali;
- jika begitu banyak versi baris dihapus selama pembersihan sehingga semuanya tidak dapat masuk ke dalam memori maintenance_work_mem , maka semua indeks akan sepenuhnya dipindai sebanyak yang diperlukan.
Pada tabel besar, ini bisa memakan banyak waktu dan membuat beban yang signifikan pada sistem. Tentu saja, permintaan tidak akan diblokir, tetapi I / O "ekstra" juga tidak menyenangkan.
Untuk mempercepat proses, masuk akal untuk memanggil pembersihan lebih sering (sehingga tidak banyak versi baris yang dihapus setiap kali), atau mengalokasikan lebih banyak memori.
Saya perhatikan dalam tanda kurung itu, dimulai dengan versi 11, PostgreSQL
dapat melewati pemindaian indeks jika ini tidak mutlak diperlukan. Ini akan membuat hidup lebih mudah bagi pemilik tabel besar di mana baris hanya ditambahkan (tetapi tidak diubah).
Pemantauan
Bagaimana memahami bahwa pembersihan tidak berhasil dengan sekali jalan?
Kami telah melihat metode pertama: Anda dapat memanggil perintah VACUUM dengan VERBOSE. Kemudian informasi tentang fase pekerjaan akan ditampilkan di konsol.
Kedua, dimulai dengan versi 9.6, ada tampilan pg_stat_progress_vacuum, yang juga berisi semua informasi yang diperlukan.
(Ada cara ketiga - untuk menampilkan informasi dalam log pesan, tetapi ini hanya berfungsi untuk pembersihan otomatis, yang akan dibahas lain kali.)
Kami akan memasukkan lebih banyak baris dalam tabel sehingga pembersihan membutuhkan waktu yang nyata, dan kami akan memperbarui semuanya sehingga ada hubungannya dengan pembersihan.
=> TRUNCATE vac; => INSERT INTO vac(s) SELECT 'A' FROM generate_series(1,500000); => UPDATE vac SET s = 'B';
Kurangi ukuran memori yang dialokasikan untuk array pengidentifikasi:
=> ALTER SYSTEM SET maintenance_work_mem = '1MB'; => SELECT pg_reload_conf();
Kami mulai membersihkan dan, saat berfungsi, kami akan beralih ke tampilan pg_stat_progress_vacuum beberapa kali:
=> VACUUM VERBOSE vac;
| => SELECT * FROM pg_stat_progress_vacuum \gx
| -[ RECORD 1 ]------+------------------ | pid | 6715 | datid | 41493 | datname | test | relid | 57383 | phase | vacuuming indexes | heap_blks_total | 16667 | heap_blks_scanned | 2908 | heap_blks_vacuumed | 0 | index_vacuum_count | 0 | max_dead_tuples | 174762 | num_dead_tuples | 174480
| => SELECT * FROM pg_stat_progress_vacuum \gx
| -[ RECORD 1 ]------+------------------ | pid | 6715 | datid | 41493 | datname | test | relid | 57383 | phase | vacuuming indexes | heap_blks_total | 16667 | heap_blks_scanned | 5816 | heap_blks_vacuumed | 2907 | index_vacuum_count | 1 | max_dead_tuples | 174762 | num_dead_tuples | 174480
Di sini kita melihat khususnya:
- nama fase saat ini (fase) - kita berbicara tentang tiga fase utama, tetapi secara umum ada lebih banyak dari mereka;
- total jumlah halaman tabel (heap_blks_total);
- jumlah halaman yang dirayapi (heap_blks_scanned);
- jumlah halaman yang sudah dibersihkan (heap_blks_vacuumed);
- jumlah pass by index (index_vacuum_count).
Kemajuan keseluruhan ditentukan oleh rasio heap_blks_vacuumed ke heap_blks_total, tetapi perlu diingat bahwa nilai ini tidak berubah dengan lancar, tetapi "tersentak-sentak" karena pemindaian indeks. Namun, perhatian utama harus diberikan pada jumlah siklus pembersihan - nilai yang lebih besar dari 1 berarti bahwa memori yang dialokasikan tidak cukup untuk menyelesaikan pembersihan dalam satu lintasan.
Output dari perintah VACUUM VERBOSE, selesai saat ini, akan menampilkan gambaran besar:
INFO: vacuuming "public.vac"
INFO: scanned index "vac_s" to remove 174480 row versions DETAIL: CPU: user: 0.50 s, system: 0.07 s, elapsed: 1.36 s INFO: "vac": removed 174480 row versions in 2908 pages DETAIL: CPU: user: 0.02 s, system: 0.02 s, elapsed: 0.13 s
INFO: scanned index "vac_s" to remove 174480 row versions DETAIL: CPU: user: 0.26 s, system: 0.07 s, elapsed: 0.81 s INFO: "vac": removed 174480 row versions in 2908 pages DETAIL: CPU: user: 0.01 s, system: 0.02 s, elapsed: 0.10 s
INFO: scanned index "vac_s" to remove 151040 row versions DETAIL: CPU: user: 0.13 s, system: 0.04 s, elapsed: 0.47 s INFO: "vac": removed 151040 row versions in 2518 pages DETAIL: CPU: user: 0.01 s, system: 0.02 s, elapsed: 0.08 s
INFO: index "vac_s" now contains 500000 row versions in 17821 pages DETAIL: 500000 index row versions were removed. 8778 index pages have been deleted, 0 are currently reusable. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: "vac": found 500000 removable, 500000 nonremovable row versions in 16667 out of 16667 pages DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4011 There were 0 unused item pointers. 0 pages are entirely empty. CPU: user: 1.10 s, system: 0.37 s, elapsed: 3.71 s. VACUUM
Di sini Anda dapat melihat bahwa secara total ada tiga lintasan melalui indeks, yang masing-masing membersihkan 174.480 pointer ke versi string mati. Dari mana asal nomor ini? Satu tautan (tid) membutuhkan 6 byte, dan 1024 * 1024/6 = 174762 adalah angka yang kita lihat di pg_stat_progress_vacuum.max_dead_tuples. Sebenarnya, ini dapat digunakan sedikit kurang: dijamin bahwa ketika membaca halaman berikutnya semua petunjuk ke versi "mati" akan pas di memori.
Analisis
Analisis, atau, dengan kata lain, pengumpulan informasi statistik untuk perencana kueri, tidak secara resmi terhubung dengan pembersihan. Namun demikian, kami dapat melakukan analisis tidak hanya dengan tim ANALYZE, tetapi juga menggabungkan pembersihan dengan analisis: VACUUM ANALYZE. Dalam hal ini, pembersihan pertama kali dilakukan, dan kemudian analisis - tidak ada penghematan.
Tetapi, seperti yang akan kita lihat nanti, pembersihan otomatis dan analisis otomatis dilakukan dalam satu proses dan dikelola dengan cara yang sama.
Pembersihan penuh (vakum penuh)
Seperti yang telah kita lihat, pembersihan konvensional membebaskan lebih banyak ruang daripada pembersihan intra-halaman, tetapi bahkan itu tidak selalu menyelesaikan masalah sepenuhnya.
Jika, karena alasan tertentu, tabel atau indeks telah tumbuh secara signifikan dalam ukuran, maka pembersihan secara teratur akan membebaskan ruang di dalam halaman yang ada: mereka akan mengandung "lubang", yang kemudian akan digunakan untuk memasukkan versi baris baru. Tetapi jumlah halaman tidak akan berubah, dan, oleh karena itu, dari sudut pandang sistem operasi, file-file tersebut akan menempati jumlah ruang yang persis sama dengan yang mereka tempati sebelum membersihkan. Dan ini buruk karena:
- pemindaian penuh atas tabel (atau indeks) melambat;
- cache buffer yang lebih besar mungkin diperlukan (karena halaman disimpan, dan kepadatan informasi bermanfaat berkurang);
- tingkat "ekstra" mungkin muncul di pohon indeks, yang akan memperlambat akses indeks;
- file mengambil ruang disk tambahan dan cadangan.
(Satu-satunya pengecualian adalah halaman yang benar-benar dibersihkan di akhir file - halaman tersebut โmenggigitโ file dan kembali ke sistem operasi.)
Jika pembagian informasi yang berguna dalam file jatuh di bawah batas yang wajar, administrator dapat melakukan pembersihan tabel penuh. Pada saat yang sama, tabel dan semua indeksnya sepenuhnya dibangun kembali dari awal, dan data dikemas sekompleks mungkin (tentu saja, dengan mempertimbangkan parameter fillfactor). Saat membangun kembali, PostgreSQL secara berurutan membangun kembali tabel terlebih dahulu, dan kemudian masing-masing indeksnya. File baru dibuat untuk setiap objek, dan pada akhir pembangunan kembali, file lama dihapus. Harap dicatat bahwa dalam proses mengerjakan disk akan membutuhkan ruang tambahan.
Untuk mengilustrasikannya, masukkan kembali sejumlah baris ke dalam tabel:
=> TRUNCATE vac; => INSERT INTO vac(s) SELECT 'A' FROM generate_series(1,500000);
Bagaimana cara mengevaluasi kepadatan informasi? Untuk melakukan ini, nyaman menggunakan ekstensi khusus:
=> CREATE EXTENSION pgstattuple; => SELECT * FROM pgstattuple('vac') \gx
-[ RECORD 1 ]------+--------- table_len | 68272128 tuple_count | 500000 tuple_len | 64500000 tuple_percent | 94.47 dead_tuple_count | 0 dead_tuple_len | 0 dead_tuple_percent | 0 free_space | 38776 free_percent | 0.06
Fungsi membaca seluruh tabel dan menunjukkan statistik tentang seberapa banyak ruang data apa yang ditempati dalam file. Informasi utama yang kami minati sekarang adalah bidang tuple_percent: persentase yang ditempati oleh data yang berguna. Itu kurang dari 100 karena overhead yang tak terelakkan dari informasi layanan di dalam halaman, tetapi masih cukup tinggi.
Untuk indeks, informasi lain ditampilkan, tetapi bidang avg_leaf_density memiliki arti yang sama: persentase informasi yang berguna (di halaman daun).
=> SELECT * FROM pgstatindex('vac_s') \gx
-[ RECORD 1 ]------+--------- version | 3 tree_level | 3 index_size | 72802304 root_block_no | 2722 internal_pages | 241 leaf_pages | 8645 empty_pages | 0 deleted_pages | 0 avg_leaf_density | 83.77 leaf_fragmentation | 64.25
Dan di sini adalah ukuran tabel dan indeks:
=> SELECT pg_size_pretty(pg_table_size('vac')) table_size, pg_size_pretty(pg_indexes_size('vac')) index_size;
table_size | index_size ------------+------------ 65 MB | 69 MB (1 row)
Sekarang hapus 90% dari semua baris. Kami memilih baris untuk dihapus secara acak, sehingga di setiap halaman dengan probabilitas tinggi setidaknya satu baris tetap:
=> DELETE FROM vac WHERE random() < 0.9;
DELETE 450189
Berapa ukuran benda setelah pembersihan normal?
=> VACUUM vac; => SELECT pg_size_pretty(pg_table_size('vac')) table_size, pg_size_pretty(pg_indexes_size('vac')) index_size;
table_size | index_size ------------+------------ 65 MB | 69 MB (1 row)
Kami melihat bahwa ukurannya tidak berubah: pembersihan rutin tidak dapat mengurangi ukuran file dengan cara apa pun. Meskipun kepadatan informasi jelas menurun sekitar 10 kali:
=> SELECT vac.tuple_percent, vac_s.avg_leaf_density FROM pgstattuple('vac') vac, pgstatindex('vac_s') vac_s;
tuple_percent | avg_leaf_density ---------------+------------------ 9.41 | 9.73 (1 row)
Sekarang periksa apa yang terjadi setelah pembersihan penuh. Berikut adalah file yang digunakan oleh tabel dan indeks sekarang:
=> SELECT pg_relation_filepath('vac'), pg_relation_filepath('vac_s');
pg_relation_filepath | pg_relation_filepath ----------------------+---------------------- base/41493/57392 | base/41493/57393 (1 row)
=> VACUUM FULL vac; => SELECT pg_relation_filepath('vac'), pg_relation_filepath('vac_s');
pg_relation_filepath | pg_relation_filepath ----------------------+---------------------- base/41493/57404 | base/41493/57407 (1 row)
Sekarang file diganti dengan yang baru. Ukuran tabel dan indeks telah menurun secara signifikan, dan kepadatan informasi telah meningkat:
=> SELECT pg_size_pretty(pg_table_size('vac')) table_size, pg_size_pretty(pg_indexes_size('vac')) index_size;
table_size | index_size ------------+------------ 6648 kB | 6480 kB (1 row)
=> SELECT vac.tuple_percent, vac_s.avg_leaf_density FROM pgstattuple('vac') vac, pgstatindex('vac_s') vac_s;
tuple_percent | avg_leaf_density ---------------+------------------ 94.39 | 91.08 (1 row)
Harap dicatat bahwa kepadatan informasi dalam indeks bahkan meningkat dibandingkan dengan aslinya. Menciptakan kembali indeks (pohon-B) dari data yang tersedia lebih menguntungkan daripada memasukkan data ke dalam indeks baris demi baris yang ada.
Fungsi ekstensi
pgstattuple yang kami gunakan membaca seluruh tabel. Jika tabelnya besar, maka ini tidak nyaman, dan karena itu ada juga fungsi pgstattuple_approx, yang melewatkan halaman yang ditandai di peta visibilitas dan menunjukkan angka perkiraan.
Cara yang lebih cepat, tetapi bahkan kurang akurat adalah memperkirakan rasio volume data dengan ukuran file dalam direktori sistem. Opsi untuk pertanyaan semacam itu dapat ditemukan
di wiki .
Pembersihan penuh tidak memerlukan penggunaan reguler, karena sepenuhnya memblokir semua pekerjaan dengan tabel (termasuk permintaannya) untuk seluruh durasi kerjanya. Jelas bahwa pada sistem yang digunakan secara aktif, ini mungkin tidak dapat diterima. Kunci akan dipertimbangkan secara terpisah, tetapi untuk saat ini kami akan membatasi diri untuk menyebutkan ekstensi
pg_repack , yang mengunci tabel hanya untuk waktu yang singkat di akhir pekerjaan.
Tim serupa
Ada beberapa perintah yang juga sepenuhnya membangun kembali tabel dan indeks, dan ini mirip dengan pembersihan lengkap. Semua dari mereka benar-benar memblokir pekerjaan dengan tabel, semuanya menghapus file data lama dan membuat yang baru.
Perintah CLUSTER serupa dalam segala hal dengan VACUUM FULL, tetapi juga secara fisik mengatur versi string sesuai dengan salah satu indeks yang tersedia. Ini memberi scheduler kemampuan untuk menggunakan akses indeks lebih efektif dalam beberapa kasus. Namun, harus dipahami bahwa pengelompokan tidak didukung: dengan perubahan berikutnya pada tabel, urutan fisik versi baris akan dilanggar.
Perintah REINDEX membangun kembali satu indeks di atas sebuah tabel. Bahkan, VACUUM FULL dan CLUSTER menggunakan perintah ini untuk membangun kembali indeks.
Perintah TRUNCATE secara logis bekerja sama dengan DELETE - menghapus semua baris tabel. Tapi HAPUS, seperti yang sudah dibahas, hanya menandai versi baris yang dihapus, yang membutuhkan pembersihan lebih lanjut. TRUNCATE baru saja membuat file baru yang bersih. Sebagai aturan, ini bekerja lebih cepat, tetapi perlu diingat bahwa TRUNCATE akan sepenuhnya memblokir pekerjaan dengan tabel sepanjang waktu sampai akhir transaksi.
Untuk dilanjutkan .