Baru-baru ini, saya memiliki server PostgreSQL 8.2.11 yang ditingkatkan menjadi 8.4 untuk memanfaatkan fitur autovacuum dan sejalan dengan 30 server PGSQL lainnya. Ini dilakukan oleh grup TI terpisah yang mengelola perangkat keras, jadi kami tidak punya banyak pilihan pada peningkatan lainnya (tidak akan melihat 9+ untuk sementara waktu). Server ada di lingkungan yang sangat tertutup (jaringan terisolasi, hak root terbatas) dan berjalan di RHEL5.5 (i686). Setelah peningkatan, basis data terus bertambah hingga 5-6 GB sehari. Biasanya, database, secara keseluruhan, ~ 20GB; Saat ini, ~ 89GB. Kami memiliki beberapa server lain yang menjalankan basis data yang setara dan benar-benar menyinkronkan rekaman satu sama lain melalui aplikasi pihak ke-3 (yang saya tidak memiliki akses ke pekerjaan dalam). Database lain adalah ~ 20GB sebagaimana mestinya.
Menjalankan SQL berikut, cukup jelas ada masalah dengan tabel tertentu, dan, lebih khusus, tabel TOAST-nya.
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 20;
Yang menghasilkan:
hubungan | ukuran ------------------------------------ + --------- pg_toast.pg_toast_16874 | 89 GB fews00.warmstates | 1095 MB ... (20 baris)
Tabel TOAST ini untuk tabel yang disebut "timeseries" yang menyimpan catatan besar data yang terkumpul. A SUM(LENGTH(blob)/1024./1024.)
dari semua catatan dalam rentang waktu menghasilkan ~ 16GB untuk kolom itu. Seharusnya tidak ada alasan tabel TOAST tabel ini harus sebesar itu.
Saya telah melakukan VACUUM FULL VERBOSE ANALYZE timeseries
, dan vakum berjalan sampai selesai tanpa kesalahan.
INFO: menyedot debu "pg_toast.pg_toast_16874"
INFO: "pg_toast_16874": ditemukan 22483 dapat dilepas, 10475318 versi baris yang tidak dapat dilepas di 10448587 halaman
DETAIL: 0 versi baris mati belum dapat dihapus.
Versi baris yang tidak dapat dilepas berkisar dari 37 hingga 2036 byte.
Ada 20121422 pointer item yang tidak digunakan.
Total ruang kosong (termasuk versi baris yang dapat dilepas) adalah 0 byte. 4944885 halaman sedang atau akan menjadi kosong, termasuk 0 pada akhir tabel. 4944885 halaman yang berisi 0 byte gratis adalah tujuan pemindahan potensial.
CPU 75.31s / 29.59u detik telah berlalu 877.79 detik.
INFO: indeks "pg_toast_16874_index" sekarang berisi 10475318 versi baris di 179931 halaman.
Detail: 23884 versi baris indeks telah dihapus.
101623 halaman indeks telah dihapus, 101623 saat ini dapat digunakan kembali.
CPU 1.35s / 2.46u detik berlalu 21.07 detik.
REINDEX tabel yang membebaskan beberapa ruang (~ 1GB). Saya tidak bisa CLUSTER tabel karena tidak ada cukup ruang pada disk untuk proses, dan saya menunggu untuk membangun kembali tabel sepenuhnya karena saya ingin mencari tahu mengapa itu jauh lebih besar daripada database setara yang kita miliki.
Jalankan kueri dari wiki PostgreSQL di sini - "Perlihatkan Basis Data" , dan inilah yang saya dapatkan:
current_database | schemaname | tablename | tbloat | wastedbytes | iname | ibloat | wastedibytes ----------------- + ------------ + ------------------- ------------- + -------- + ------------- + ------------- -------------------- + -------- + -------------- ptrdb04 | fews00 | deret waktu | 1.0 | 0 | idx_timeseries_synchlevel | 0,0 | 0 ptrdb04 | fews00 | deret waktu | 1.0 | 0 | idx_timeseries_localavail | 0,0 | 0 ptrdb04 | fews00 | deret waktu | 1.0 | 0 | idx_timeseries_expirytime | 0,0 | 0 ptrdb04 | fews00 | deret waktu | 1.0 | 0 | idx_timeseries_expiry_null | 0,0 | 0 ptrdb04 | fews00 | deret waktu | 1.0 | 0 | uniq_localintid | 0,0 | 0 ptrdb04 | fews00 | deret waktu | 1.0 | 0 | pk_timeseries | 0,1 | 0 ptrdb04 | fews00 | idx_timeseries_expiry_null | 0,6 | 0 | ? | 0,0 | 0
Sepertinya database tidak menganggap ruang ini sebagai "kosong," sama sekali, tetapi saya tidak melihat dari mana semua ruang disk berasal!
Saya menduga bahwa server database ini memutuskan untuk menggunakan ruang disk sebanyak 4-5x untuk menyimpan catatan yang sama dengan yang diambil dari server data lainnya. Pertanyaan saya adalah ini: Apakah ada cara saya dapat memverifikasi ukuran disk fisik suatu baris? Saya ingin membandingkan ukuran satu baris pada database ini dengan database "sehat" lainnya.
Terima kasih atas bantuan yang Anda berikan!
PEMBARUAN 1
Saya akhirnya membangun kembali tabel dari skema dibuang karena ukurannya (tidak bisa meninggalkannya sendirian untuk hari lain). Setelah menyinkronkan data, melalui proses sinkronisasi perangkat lunak, tabel TOAST ~ 35GB; namun, saya hanya bisa menjelaskan ~ 9GB dari kolom gumpalan yang seharusnya paling panjang dalam hal nilai. Tidak yakin dari mana 26GB lainnya berasal. CLUSTERed, VACUUM FULLed, dan REINDEXed tidak berhasil. File postgresql.conf antara server data lokal dan jarak jauh persis sama. Apakah ada alasan database ini mungkin mencoba untuk menyimpan setiap catatan dengan ruang yang lebih besar pada disk?
PEMBARUAN 2 - Diperbaiki
Saya akhirnya memutuskan untuk benar-benar membangun kembali database dari awal hingga menginstal ulang paket-paket PostgreSQL84 pada sistem. Jalur basis data diinisialisasi ulang dan tablespace dibersihkan. Proses sinkronisasi perangkat lunak pihak ke-3 mengisi kembali tabel, dan ukuran akhirnya menjadi ~ 12GB ! Sayangnya, ini, sama sekali tidak, membantu menyelesaikan apa sumber sebenarnya dari masalah itu di sini. Saya akan menontonnya selama satu atau dua hari dan melihat apakah ada perbedaan besar dengan bagaimana database yang direvitalisasi menangani tabel TOAST dan memposting hasilnya di sini.
Ukuran Relasi
ptrdb04=> SELECT nspname || '.' || relname AS "relation",
ptrdb04-> pg_size_pretty(pg_relation_size(C.oid)) AS "size"
ptrdb04-> FROM pg_class C
ptrdb04-> LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
ptrdb04-> WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ptrdb04-> ORDER BY pg_relation_size(C.oid) DESC
ptrdb04-> LIMIT 2;
hubungan | ukuran
------------------------- + ---------
pg_toast . pg_toast_17269 | 18 GB
fews00 . keadaan hangat | 1224 MB
( 2 baris )
VACUUM VERBOSE ANALYZE timeseries;
INFO: "timeseries": ditemukan 12699 versi baris yang dapat dilepas, 681961 tidak dapat dihapus dalam 58130 dari 68382 halaman RINCIAN: 0 versi baris mati belum dapat dihapus. Ada 105.847 pointer item yang tidak digunakan. 0 halaman sepenuhnya kosong. CPU 0.83s / 2.08u detik berlalu 33.36 detik. INFO: menyedot debu "pg_toast.pg_toast_17269" INFO: indeks yang dipindai "pg_toast_17269_index" untuk menghapus versi 2055849 baris DETAIL: CPU 0.37s / 2.92u detik telah berlalu 13.29 detik. INFO: "pg_toast_17269": menghapus versi 2055849 baris dalam 518543 halaman DETAIL: CPU 8.60s / 3.21u detik berlalu 358,42 detik. INFO: indeks "pg_toast_17269_index" sekarang mengandung 7346902 versi baris dalam 36786 halaman DETAIL: 2055849 versi baris indeks telah dihapus. Halaman indeks 10410 telah dihapus, 5124 saat ini dapat digunakan kembali. CPU 0,00s / 0,00u detik berlalu 0,01 detik. INFO: "pg_toast_17269": ditemukan 1286128 dapat dilepas, 2993389 versi baris yang tidak dapat dihapus dalam 1257871 dari 2328079 halaman RINCIAN: 0 versi baris mati belum dapat dihapus. Ada 18847 pointer item yang tidak digunakan. 0 halaman sepenuhnya kosong. CPU 26.56s / 13.04u detik telah berlalu 714.97 detik. INFO: menganalisis "fews00.timeseries" INFO: "timeseries": memindai 30000 dari 68382 halaman, berisi 360192 baris hidup dan 0 baris mati; 30000 baris dalam sampel, 821022 memperkirakan total baris
Satu-satunya perbedaan yang terlihat setelah pembangunan kembali (selain penggunaan disk) adalah
INFO: "pg_toast_17269": ditemukan 1286128 dapat dilepas, 2993389 versi baris yang tidak dapat dihapusseperti @CraigRinger disebutkan dalam komentar. Hitungan baris yang tidak dapat dilepas jauh lebih kecil dari sebelumnya.
Pertanyaan baru: Dapatkah tabel lain memengaruhi ukuran tabel lain? (melalui kunci asing dan semacamnya) Membangun kembali tabel tidak melakukan apa-apa, namun membangun kembali seluruh database terbukti untuk memperbaiki masalah.
sumber
Jawaban:
Ini:
menunjukkan bahwa masalah mendasar adalah bahwa sesuatu masih dapat "melihat" baris-baris itu sehingga tidak dapat dihapus.
Kandidat untuk itu adalah:
Kehilangan transaksi yang disiapkan. Periksa
pg_catalog.pg_prepared_xacts
; itu harus kosong. Juga jalankanSHOW max_prepared_transactions
; itu harus melaporkan nol.Sesi jangka panjang dengan transaksi terbuka dan tidak aktif Dalam PostgreSQL 8.4 dan di atasnya, ini hanya akan menjadi masalah untuk
SERIALIZABLE
transaksi. Periksapg_catalog.pg_stat_activity
untuk<IDLE> in transaction
sesi.Kemungkinan besar Anda memiliki klien yang gagal melakukan atau mengembalikan transaksi selama periode siaga yang lama.
Jika ini ternyata bukan, hal berikutnya yang akan saya periksa adalah melakukan penjumlahan
octet_size
dari setiap kolom pada tabel minat. Bandingkanpg_relation_size
dengan tabel danTOAST
sisi meja. Jika ada perbedaan besar maka ruang yang dikonsumsi kemungkinan tidak lagi terlihat baris dan Anda mungkin memiliki masalah mengasapi meja. Jika mereka sangat mirip, Anda dapat mulai mempersempit di mana penggunaan ruang adalah dengan menjumlahkan ukuran oktet per kolom, mendapatkan nilai 'n' teratas, dll.sumber
SELECT * FROM pg_stat_activity WHERE current_query LIKE '<IDLE>%';
yang menghasilkan sekitar 30-40 hasil; Namun, ini tampaknya cukup normal. Saya memeriksa beberapa server "sehat", dan semuanya sama.<IDLE> in transaction
, dan hanya jika mereka telah (a) diam untuk sementara waktu dan (b) menggunakanSERIALIZABLE
isolasi atau Anda berada di 8.3 atau lebih tua.TOAST
meja yang tampak membengkak. BTW, jika Anda telah menggunakanVACUUM FULL
banyak pada server pre-9.0 Anda akan inginREINDEX
sepertiVACUUM FULL
pada versi-versi itu dapat menyebabkan indeks signifikan. Saya sekarang bertanya-tanya apakah seseorang menetapkan absurdFILLFACTOR
di atas meja roti panggang, meskipun itu seharusnya tidak membiarkan Anda melewati konsumsi ruang 10x.Saya tidak tahu mengapa itu kembung. Tapi saya melakukan beberapa pencarian dan mungkin tautan ini memiliki beberapa wawasan: http://postgresql.1045698.n5.nabble.com/A-154-GB-table-swelled-to-527-GB-on-the-Slony-slave -Cara-untuk-memadatkannya-td5543034.html ... Ini bukan situasi Anda yang sebenarnya, tetapi mungkin itu cukup dekat untuk membantu Anda mencapai bagian bawah phatom bloat .
Namun, saya pikir satu-satunya cara untuk memadatkan tabel pada saat ini adalah dengan CLUSTER. Karena Anda kekurangan ruang disk, itu masalah.
Inilah saran saya untuk itu: buat tablespace pada drive yang berbeda dengan banyak ruang ekstra, kemudian tetapkan tabel masalah Anda ke tablespace tersebut. PostgreSQL akan menyalin tabel ke tablespace baru (mungkin menguncinya dalam proses, sehingga Anda akan memerlukan jendela pemeliharaan). Kemudian VACFULL tabel (membersihkan sebagian besar ruang lama yang dikonsumsi oleh tabel di tablespace default). Kemudian CLUSTER meja dan itu harus dipadatkan. Kemudian taruh kembali di tablespace default dan jalankan VACFULL lagi (untuk membersihkan ruang yang tidak terpakai di tablespace baru).
sumber