TOAST Pertumbuhan Tabel Tak Terkendali - FULLVAC Tidak Melakukan Apa-apa

9

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 dihapus
seperti @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.

BrM13
sumber
Mengapa Anda tidak langsung meningkatkan ke 9.2? Ini bahkan memiliki lebih banyak peningkatan di bidang vaccum daripada 8,4 (dan 8,4 akan menjadi EOL tahun depan pula)
a_horse_with_no_name
Saya telah memperbarui pos. Upgrade tidak dilakukan oleh toko kami dan tidak harus dengan permintaan kami. Sayangnya, kami tidak memiliki opsi itu untuk meningkatkan ke 9+.
BrM13
BAIK. Saya hanya ingin memastikan Anda tidak mengabaikan yang sudah jelas;)
a_horse_with_no_name

Jawaban:

9

Ini:

INFO: "pg_toast_16874": found 22483 removable, 10475318 nonremovable row versions in 10448587 pages 22483 removable, 10475318 nonremovable row versions in 10448587 pages

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 jalankan SHOW 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 SERIALIZABLEtransaksi. Periksa pg_catalog.pg_stat_activityuntuk <IDLE> in transactionsesi.

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_sizedari setiap kolom pada tabel minat. Bandingkan pg_relation_sizedengan tabel dan TOASTsisi 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.

Craig Ringer
sumber
1) pg_prepared_xacts dan max_prepared_transactions memang kembali kosong. 2) Pasti ada beberapa transaksi IDLE 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.
BrM13
3) Inilah yang saya lakukan. Melingkari kolom timeseries, menarik octet_length (kolom). Kalikan setiap nilai dengan jumlah baris dan jumlahkan. Untuk timeseries, saya mendapat ~ 430MB (dekat dengan 493MB dari pg_relation_size) dan 438MB untuk tabel TOAST (menggunakan kolom chunk_id, chunk_seq, chunk_data). Estimasi terlihat benar, dan tabel TOAST adalah WAY off relation_size oleh sekitar 2 urutan besarnya (60GB hari ini). Sepertinya saya mengalami kembung, tetapi bukan jenis tradisional (kembung yang tidak digunakan). Jika tidak, FULLVAC harus mengatasi masalahnya.
BrM13
Sesi @Brad Idle baik-baik saja, itu hanya sesi iseng dengan transaksi terbuka yang menjadi masalah, yaitu <IDLE> in transaction, dan hanya jika mereka telah (a) diam untuk sementara waktu dan (b) menggunakan SERIALIZABLEisolasi atau Anda berada di 8.3 atau lebih tua.
Craig Ringer
@Brad Sangat menarik bahwa hanya TOASTmeja yang tampak membengkak. BTW, jika Anda telah menggunakan VACUUM FULLbanyak pada server pre-9.0 Anda akan ingin REINDEXseperti VACUUM FULLpada versi-versi itu dapat menyebabkan indeks signifikan. Saya sekarang bertanya-tanya apakah seseorang menetapkan absurd FILLFACTORdi atas meja roti panggang, meskipun itu seharusnya tidak membiarkan Anda melewati konsumsi ruang 10x.
Craig Ringer
Terima kasih atas klarifikasi IDLE. Saya pikir itu yang Anda maksud, tapi itu baik untuk mengetahui dengan pasti. Sedangkan untuk FILLFACTOR, tabel menggunakan default. FYI - Menurut dokumentasi 8.4 CREATE TABLE , standarnya adalah 100, dan Anda tidak dapat menetapkan FILLFACTOR untuk tabel TOAST.
BrM13
0

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).

efesar
sumber
Saya benar-benar akhirnya membangun kembali tabel (membuang skema dan membangun kembali dari itu) dan menarik data langsung dari salah satu basis data jauh. Setelah proses selesai, basis data masih 35GB dengan hanya 9GB yang dihitung oleh kolom "lebar". CLUSTERed, VACUUM FULLed, REINDEXed, dan saya masih duduk di ton penggunaan disk misterius.
BrM13
Tautan sudah mati :(
hayd