Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
IO: DataFileRead
Peristiwa IO:DataFileRead terjadi saat koneksi menunggu proses backend untuk membaca halaman yang diperlukan dari penyimpanan karena halaman tidak tersedia dalam memori bersama.
Versi mesin yang didukung
Informasi peristiwa tunggu ini didukung untuk semua versi RDS for PostgreSQL.
Konteks
Semua kueri dan operasi manipulasi data (DML) mengakses halaman di pool buffer. Pernyataan yang dapat menimbulkan pembacaan mencakup SELECT, UPDATE, dan DELETE. Misalnya, UPDATE dapat membaca halaman dari tabel atau indeks. Jika halaman yang diminta atau diperbarui tidak berada dalam pool buffer bersama, pembacaan ini dapat mengarah ke peristiwa IO:DataFileRead.
Karena bersifat terbatas, pool buffer bersama dapat diisi. Dalam hal ini, permintaan untuk halaman yang tidak berada dalam memori memaksa basis data untuk membaca blok dari disk. Jika peristiwa IO:DataFileRead sering terjadi, pool buffer bersama mungkin terlalu kecil untuk mengakomodasi beban kerja Anda. Masalah ini bersifat akut untuk kueri yang membaca sejumlah besar baris yang tidak dapat ditampung pool buffer. Untuk informasi selengkapnya tentang pool buffer, lihat Resource ConsumptionSELECT
Kemungkinan penyebab peningkatan peristiwa tunggu
Penyebab umum peristiwa IO:DataFileRead tersebut mencakup:
- Lonjakan koneksi
-
Anda mungkin menemukan beberapa koneksi yang menghasilkan jumlah acara IO: DataFileRead wait yang sama. Dalam hal ini, lonjakan (peningkatan tiba-tiba dan besar) dalam peristiwa
IO:DataFileReaddapat terjadi. - Pernyataan SELECT dan DML yang melakukan pemindaian berurutan
-
Aplikasi Anda mungkin melakukan operasi baru. Operasi yang ada mungkin juga berubah karena rencana eksekusi baru. Dalam kasus ini, cari tabel (terutama tabel besar) yang memiliki nilai
seq_scanyang lebih besar. Temukan tabel dengan membuat kueripg_stat_user_tables. Untuk melacak kueri yang menghasilkan lebih banyak operasi baca, gunakan ekstensipg_stat_statements. - CTAS dan CREATE INDEX untuk set data besar
-
CTAS adalah sebuah pernyataan
CREATE TABLE AS SELECT. Jika Anda menjalankan CTAS menggunakan set data besar sebagai sumber, atau membuat indeks pada tabel besar, maka peristiwaIO:DataFileReaddapat terjadi. Saat Anda membuat indeks, basis data mungkin perlu membaca seluruh objek menggunakan pemindaian berurutan. CTAS menghasilkan pembacaanIO:DataFilesaat halaman tidak ada dalam memori. - Beberapa pekerja vakum berjalan pada waktu yang sama
-
Pekerja vakum dapat dipicu secara manual atau otomatis. Sebaiknya adopsi strategi vakum yang agresif. Namun, saat tabel memiliki banyak baris yang diperbarui atau dihapus, peristiwa tunggu
IO:DataFileReadbertambah. Setelah ruang direklamasi, waktu vakum yang dihabiskan untukIO:DataFileReadakan berkurang. - Menyerap data dalam jumlah besar
-
Saat aplikasi Anda menyerap data dalam jumlah besar, operasi
ANALYZEmungkin terjadi lebih sering. ProsesANALYZEdapat dipicu oleh peluncur autovacuum atau diinvokasi secara manual.Operasi
ANALYZEmembaca subset dari tabel. Jumlah halaman yang harus dipindai dihitung menggunakan perkalian 30 dengan nilaidefault_statistics_target. Untuk informasi selengkapnya, lihat Dokumentasi PostgreSQL. Parameter default_statistics_targetmenerima nilai antara 1 hingga 10.000, dengan nilai default adalah 100. - Kekurangan sumber daya
-
Jika bandwidth jaringan instans atau CPU dikonsumsi, peristiwa
IO:DataFileReadmungkin terjadi lebih sering.
Tindakan
Kami merekomendasikan berbagai tindakan, tergantung pada penyebab peristiwa tunggu Anda.
Topik
Memeriksa filter predikat untuk kueri yang menghasilkan peristiwa tunggu
Asumsikan bahwa Anda mengidentifikasi kueri spesifik yang menghasilkan peristiwa tunggu IO:DataFileRead. Anda dapat mengidentifikasinya menggunakan teknik berikut:
-
Wawasan Performa
-
Tampilan katalog seperti yang disediakan oleh ekstensi
pg_stat_statements -
Tampilan katalog
pg_stat_all_tables, jika secara berkala menunjukkan peningkatan jumlah pembacaan fisik -
Tampilan
pg_statio_all_tables, jika menunjukkan bahwa penghitung_readmeningkat
Sebaiknya Anda menentukan filter yang akan digunakan dalam predikat (klausa WHERE) kueri ini. Ikuti pedoman berikut:
-
Jalankan perintah
EXPLAIN. Pada output, identifikasi jenis pemindaian yang digunakan. Pemindaian berurutan tidak selalu menunjukkan adanya masalah. Kueri yang menggunakan pemindaian berurutan secara alami menghasilkan lebih banyak peristiwaIO:DataFileReadjika dibandingkan dengan kueri yang menggunakan filter.Cari tahu apakah kolom yang tercantum dalam klausa
WHEREtelah diindeks. Jika tidak, coba buat indeks untuk kolom ini. Pendekatan ini mencegah pemindaian berurutan dan mengurangi peristiwaIO:DataFileRead. Jika kueri memiliki filter yang ketat dan masih menghasilkan pemindaian berurutan, evaluasi apakah indeks yang tepat sedang digunakan. -
Cari tahu apakah kueri mengakses tabel yang sangat besar. Dalam beberapa kasus, partisi tabel dapat meningkatkan performa, dengan memungkinkan kueri hanya membaca partisi yang diperlukan.
-
Periksa kardinalitas (jumlah total baris) dari operasi gabungan Anda. Perhatikan seberapa ketat nilai yang Anda teruskan di filter untuk klausa
WHEREAnda. Jika memungkinkan, setel kueri Anda untuk mengurangi jumlah baris yang diteruskan di setiap langkah rencana.
Meminimalkan efek operasi pemeliharaan
Operasi pemeliharaan seperti VACUUM dan ANALYZE bersifat penting. Sebaiknya jangan dinonaktifkan karena peristiwa tunggu IO:DataFileRead berkaitan dengan operasi pemeliharaan ini. Pendekatan berikut dapat meminimalkan efek operasi ini:
-
Jalankan operasi pemeliharaan secara manual selama di luar jam sibuk. Teknik ini mencegah basis data mencapai ambang batas untuk operasi otomatis.
-
Untuk tabel yang sangat besar, pertimbangkan untuk mempartisi tabel. Teknik ini mengurangi overhead operasi pemeliharaan. Basis data hanya mengakses partisi yang membutuhkan pemeliharaan.
-
Saat Anda menyerap data dalam jumlah besar, coba nonaktifkan fitur analisis otomatis.
Fitur autovacuum secara otomatis dipicu untuk tabel saat rumus berikut benar.
pg_stat_user_tables.n_dead_tup > (pg_class.reltuples x autovacuum_vacuum_scale_factor) + autovacuum_vacuum_threshold
Tampilan pg_stat_user_tables dan katalog pg_class berisi beberapa baris. Satu baris dapat sesuai dengan satu baris di tabel Anda. Rumus ini mengasumsikan bahwa reltuples adalah untuk tabel tertentu. Parameter autovacuum_vacuum_scale_factor (0,20 secara default) dan autovacuum_vacuum_threshold (50 tuple secara default) biasanya diatur secara global untuk seluruh instans. Namun, Anda dapat mengatur nilai yang berbeda untuk tabel tertentu.
Topik
Temukan tabel yang mengonsumsi ruang secara tidak perlu
Untuk menemukan tabel yang menghabiskan ruang secara tidak perlu, Anda dapat menggunakan fungsi dari ekstensi pgstattuple PostgreSQL. Ekstensi (modul) ini tersedia secara default di semua instans DB RDS for PostgreSQL dan dapat diinstansiasi pada instans dengan perintah berikut.
CREATE EXTENSION pgstattuple;
Untuk informasi selengkapnya tentang ekstensi ini, lihat pgstattuple
Anda dapat memeriksa bloat tabel dan indeks di aplikasi Anda. Untuk informasi selengkapnya, lihat Mendiagnosis bloat tabel dan indeks.
Temukan tabel yang mengonsumsi ruang secara tidak perlu
Untuk menemukan indeks yang mengalami bloat dan memperkirakan jumlah ruang yang dikonsumsi secara tidak perlu pada tabel yang hak akses bacanya Anda miliki, Anda dapat menjalankan kueri berikut.
-- WARNING: rows with is_na = 't' are known to have bad statistics ("name" type is not supported). -- This query is compatible with PostgreSQL 8.2 and later. SELECT current_database(), nspname AS schemaname, tblname, idxname, bs*(relpages)::bigint AS real_size, bs*(relpages-est_pages)::bigint AS extra_size, 100 * (relpages-est_pages)::float / relpages AS extra_ratio, fillfactor, bs*(relpages-est_pages_ff) AS bloat_size, 100 * (relpages-est_pages_ff)::float / relpages AS bloat_ratio, is_na -- , 100-(sub.pst).avg_leaf_density, est_pages, index_tuple_hdr_bm, -- maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, sub.reltuples, sub.relpages -- (DEBUG INFO) FROM ( SELECT coalesce(1 + ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)), 0 -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth) ) AS est_pages, coalesce(1 + ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0 ) AS est_pages_ff, bs, nspname, table_oid, tblname, idxname, relpages, fillfactor, is_na -- , stattuple.pgstatindex(quote_ident(nspname)||'.'||quote_ident(idxname)) AS pst, -- index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples -- (DEBUG INFO) FROM ( SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, relam, table_oid, fillfactor, ( index_tuple_hdr_bm + maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign ELSE index_tuple_hdr_bm%maxalign END + nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN WHEN nulldatawidth = 0 THEN 0 WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign ELSE nulldatawidth::integer%maxalign END )::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na -- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO) FROM ( SELECT i.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.relam, a.attrelid AS table_oid, current_setting('block_size')::numeric AS bs, fillfactor, CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?) WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END AS maxalign, /* per page header, fixed size: 20 for 7.X, 24 for others */ 24 AS pagehdr, /* per page btree opaque data */ 16 AS pageopqdata, /* per tuple header: add IndexAttributeBitMapData if some cols are null-able */ CASE WHEN max(coalesce(s.null_frac,0)) = 0 THEN 2 -- IndexTupleData size ELSE 2 + (( 32 + 8 - 1 ) / 8) -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8) END AS index_tuple_hdr_bm, /* data len: we remove null values save space using it fractionnal part from stats */ sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth, max( CASE WHEN a.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na FROM pg_attribute AS a JOIN ( SELECT nspname, tbl.relname AS tblname, idx.relname AS idxname, idx.reltuples, idx.relpages, idx.relam, indrelid, indexrelid, indkey::smallint[] AS attnum, coalesce(substring( array_to_string(idx.reloptions, ' ') from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor FROM pg_index JOIN pg_class idx ON idx.oid=pg_index.indexrelid JOIN pg_class tbl ON tbl.oid=pg_index.indrelid JOIN pg_namespace ON pg_namespace.oid = idx.relnamespace WHERE pg_index.indisvalid AND tbl.relkind = 'r' AND idx.relpages > 0 ) AS i ON a.attrelid = i.indexrelid JOIN pg_stats AS s ON s.schemaname = i.nspname AND ((s.tablename = i.tblname AND s.attname = pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE)) -- stats from tbl OR (s.tablename = i.idxname AND s.attname = a.attname)) -- stats from functional cols JOIN pg_type AS t ON a.atttypid = t.oid WHERE a.attnum > 0 GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9 ) AS s1 ) AS s2 JOIN pg_am am ON s2.relam = am.oid WHERE am.amname = 'btree' ) AS sub -- WHERE NOT is_na ORDER BY 2,3,4;
Temukan tabel yang memenuhi syarat untuk di-autovacuum
Untuk menemukan tabel yang memenuhi syarat untuk autovacuum, jalankan kueri berikut.
--This query shows tables that need vacuuming and are eligible candidates. --The following query lists all tables that are due to be processed by autovacuum. -- During normal operation, this query should return very little. WITH vbt AS (SELECT setting AS autovacuum_vacuum_threshold FROM pg_settings WHERE name = 'autovacuum_vacuum_threshold') , vsf AS (SELECT setting AS autovacuum_vacuum_scale_factor FROM pg_settings WHERE name = 'autovacuum_vacuum_scale_factor') , fma AS (SELECT setting AS autovacuum_freeze_max_age FROM pg_settings WHERE name = 'autovacuum_freeze_max_age') , sto AS (SELECT opt_oid, split_part(setting, '=', 1) as param, split_part(setting, '=', 2) as value FROM (SELECT oid opt_oid, unnest(reloptions) setting FROM pg_class) opt) SELECT '"'||ns.nspname||'"."'||c.relname||'"' as relation , pg_size_pretty(pg_table_size(c.oid)) as table_size , age(relfrozenxid) as xid_age , coalesce(cfma.value::float, autovacuum_freeze_max_age::float) autovacuum_freeze_max_age , (coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples) as autovacuum_vacuum_tuples , n_dead_tup as dead_tuples FROM pg_class c JOIN pg_namespace ns ON ns.oid = c.relnamespace JOIN pg_stat_all_tables stat ON stat.relid = c.oid JOIN vbt on (1=1) JOIN vsf ON (1=1) JOIN fma on (1=1) LEFT JOIN sto cvbt ON cvbt.param = 'autovacuum_vacuum_threshold' AND c.oid = cvbt.opt_oid LEFT JOIN sto cvsf ON cvsf.param = 'autovacuum_vacuum_scale_factor' AND c.oid = cvsf.opt_oid LEFT JOIN sto cfma ON cfma.param = 'autovacuum_freeze_max_age' AND c.oid = cfma.opt_oid WHERE c.relkind = 'r' AND nspname <> 'pg_catalog' AND ( age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float) or coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples <= n_dead_tup -- or 1 = 1 ) ORDER BY age(relfrozenxid) DESC;
Merespons jumlah koneksi yang tinggi
Saat Anda memantau Amazon CloudWatch, Anda mungkin menemukan bahwa DatabaseConnections metrik melonjak. Peningkatan ini menunjukkan bertambahnya jumlah koneksi ke basis data Anda. Sebaiknya lakukan pendekatan berikut:
-
Membatasi jumlah koneksi yang dapat dibuka aplikasi dengan setiap instans. Jika aplikasi Anda memiliki fitur kumpulan koneksi tertanam, tetapkan jumlah koneksi yang wajar. Dasarkan angka pada apa yang dapat diparalelkan oleh v CPUs dalam instance Anda secara efektif.
Jika aplikasi Anda tidak menggunakan fitur kumpulan koneksi, coba gunakan Proksi Amazon RDS atau alternatifnya. Pendekatan ini memungkinkan aplikasi Anda membuka beberapa koneksi dengan penyeimbang beban. Penyeimbang selanjutnya dapat membuka sejumlah koneksi terbatas dengan basis data. Karena lebih sedikit koneksi yang berjalan secara paralel, instans DB Anda melakukan lebih sedikit peralihan konteks di kernel. Kueri harus berkembang lebih cepat, yang mengarah ke lebih sedikit peristiwa tunggu. Untuk informasi selengkapnya, lihat Proksi Amazon RDS Aurora.
-
Jika memungkinkan, manfaatkan replika baca RDS for PostgreSQL. Saat aplikasi Anda menjalankan operasi hanya-baca, kirim permintaan ini ke replika pembaca. Teknik ini mengurangi I/O tekanan pada simpul primer (penulis).
-
Coba naikkan skala instans DB Anda. Kelas instans berkapasitas lebih tinggi memberikan memori lebih banyak, yang memberi RDS for PostgreSQL pool buffer bersama yang lebih besar untuk menampung halaman. Ukuran yang lebih besar juga memberi instans DB lebih banyak v CPUs untuk menangani koneksi. Lebih CPUs banyak v sangat membantu ketika operasi yang menghasilkan peristiwa
IO:DataFileReadtunggu ditulis.