Bagaimana cara mendapatkan kembali ruang disk di PostgreSQL?

25

Saya memiliki instalasi lokal dari database 9.1 dengan beberapa tabel yang memiliki cca. 300 juta catatan dan basis data tumbuh sekitar 20 GB. Setelah itu saya mengeluarkan delete fromperintah untuk menghapus semua catatan dari itu (saya seharusnya menggunakan truncate, tapi saya tidak tahu itu). Jadi saya melakukan vakum penuh pada db saya untuk merebut kembali ruang disk, tetapi itu tidak membantu. Masalah saya terlihat identik dengan yang satu ini , tetapi tidak ada solusi yang diberikan. Saya telah memeriksa utas ini dan dokumentasi tentang "memulihkan ruang disk" , tetapi masih tidak dapat menemukan solusi. Saya menggunakan kode ini untuk mendapatkan ukuran semua tabel

 SELECT nspname || '.' || relname AS "relation",
 pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
 FROM pg_class C
 LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
 WHERE nspname NOT IN ('pg_catalog', 'information_schema')
 AND C.relkind <> 'i'
 AND nspname !~ '^pg_toast'
 ORDER BY pg_total_relation_size(C.oid) DESC
 LIMIT 15;

Namun, totalnya kurang dari 1GB

SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database 

masih menunjukkan sekitar 20 GB. Setiap saran sangat dihargai.

Komunitas
sumber
Nah, ukuran Anda permintaan tidak termasuk: indeks, tabel dalam pg_catalog, dan tabel di information_schema. Jadi coba lihat apakah itu salah satunya dengan menghapus batasan-batasan dalam WHEREklausa. Tolong tunjukkan versi PostgreSQL yang tepat ( SELECT version()) dan apa yang sebenarnya Anda lakukan untuk "menyedot database lengkap", yaitu perintah yang tepat. Jika memungkinkan, jalankan VACUUM FULL VERBOSE;(tanpa argumen) dan tempel output di suatu tempat kemudian tautkan ke sini.
Craig Ringer
Coba jatuhkan database. Anda mungkin juga mencoba membuang database, dan kemudian mengembalikannya akan membuang sampah.
jb.
1
@ jb Itu berhasil, tapi seharusnya tidak perlu. Lebih baik belajar apa masalahnya.
Craig Ringer

Jawaban:

22

Meskipun Anda tidak menyatakannya, saya menganggap dari referensi Anda ke dokumen yang telah Anda ikuti bahwa Anda telah melakukan PENUH VACUUM pada database dan / atau tabel yang terpengaruh. Anda juga tidak menentukan versi postgresql apa yang Anda gunakan - Saya akan menganggap itu> 9.0 (VACUUM FULL berperilaku berbeda sebelum ini).

VACUUM FULL akan menulis ulang tabel yang terpengaruh ke file baru, lalu menghapus file lama. Namun, jika ada proses yang masih memiliki file lama terbuka, sistem operasi tidak akan benar-benar menghapus file - sampai proses terakhir telah menutupnya.

Jika praktis, me-restart database akan memastikan bahwa semua file yang terbuka ditutup.

Jika itu tidak praktis, maka Anda mungkin dapat memverifikasi apakah ini masalah Anda, dan mencari tahu proses mana yang membuka file.

Jika menggunakan Linux (atau sebagian besar sistem mirip Unix lainnya) Anda dapat menggunakan perintah 'lsof' untuk mendapatkan daftar semua file yang terbuka di semua proses. File yang terbuka tetapi yang sudah dihapus akan memiliki '(dihapus)' ditambahkan ke nama file. Jadi, Anda dapat menangkap output lsof, mencari file yang dihapus, seperti ini:

sudo lsof -u postgres | grep 'deleted'

Jika itu mengidentifikasi proses yang masih membuka file lama, Anda dapat menggunakan pg_terminate_backend untuk mengakhiri proses itu:

SELECT pg_terminate_backend(xxx);

di mana xxx adalah PID dari proses, ditemukan di output lsof.

Jika menggunakan Windows, prinsip yang sama dapat diterapkan, karena postgres membuka file menggunakan flag FILE_SHARE_DELETE, yang memungkinkannya untuk menghapus file yang terbuka di proses lain. Perintah ' handle ' adalah setara dengan lsof, walaupun saya tidak yakin apakah Anda dapat mengetahui apakah file-file tersebut dihapus atau tidak sehingga beberapa pekerjaan tambahan mungkin diperlukan.

Ini adalah pertanyaan lain mengapa proses seperti itu akan bergantung pada pegangan file lama. Namun dalam utas yang Anda kutip dalam pertanyaan Anda, Tom Lane tampaknya menyiratkan bahwa itu bisa terjadi.

berbahaya
sumber
Saya harus segera mendapatkan ruang disk jadi saya menjatuhkan database dan mengembalikannya dari cadangan. Namun "bagaimana" menyelesaikan masalah ini masih sangat berharga untuk kasus-kasus di masa depan. Database saya adalah 9.1, win 8 64 bit, apakah penamaan file (kasus file terbuka) berlaku dengan cara yang sama seperti di linux?
@arcull OK, saya tidak menyadari Anda menggunakan Windows. Saya menambahkan beberapa info ke jawaban tentang bagaimana ini berlaku untuk Windows. Jika menurut Anda itu mungkin jawaban yang berguna, harap pertimbangkan peningkatan karena membuatnya lebih mudah bagi orang lain untuk menemukannya.
berbahaya