PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PostgreSQL Berjalan Lambat? Tips &Trik Menuju Sumbernya

Sebagai Administrator Database PostgreSQL, ada harapan setiap hari untuk memeriksa cadangan, menerapkan perubahan DDL, memastikan log tidak memiliki game yang melanggar ERROR, dan menjawab panggilan panik dari pengembang yang laporannya berjalan dua kali lebih lama dari biasanya dan mereka adakan rapat dalam sepuluh menit.

Bahkan dengan pemahaman yang baik tentang kesehatan database yang dikelola, akan selalu ada kasus baru dan masalah baru yang muncul terkait dengan kinerja dan bagaimana database "terasa". Baik itu email panik, atau tiket terbuka untuk "database terasa lambat", tugas umum ini umumnya dapat diikuti dengan beberapa langkah untuk memeriksa apakah ada masalah dengan PostgreSQL atau tidak, dan apa masalahnya.

Ini sama sekali bukan panduan lengkap, juga langkah-langkahnya tidak perlu dilakukan dalam urutan tertentu. Tapi ini lebih merupakan serangkaian langkah awal yang dapat diambil untuk membantu menemukan pelanggar umum dengan cepat, serta mendapatkan wawasan baru tentang apa masalahnya. Pengembang mungkin tahu bagaimana aplikasi bertindak dan merespons, tetapi Administrator Basis Data tahu bagaimana basis data bertindak dan merespons aplikasi, dan bersama-sama, masalahnya dapat ditemukan.

CATATAN: Kueri yang akan dieksekusi harus dilakukan sebagai pengguna super, seperti 'postgres' atau pengguna basis data mana pun yang diberikan izin pengguna super. Pengguna terbatas akan ditolak atau datanya dihilangkan.

Langkah 0 - Pengumpulan Informasi

Dapatkan informasi sebanyak mungkin dari siapa pun yang mengatakan database tampak lambat; kueri tertentu, aplikasi yang terhubung, jangka waktu kelambatan kinerja, dll. Semakin banyak informasi yang diberikan, semakin mudah untuk menemukan masalahnya.

Langkah 1 - Periksa pg_stat_activity

Permintaan mungkin datang dalam berbagai bentuk, tetapi jika "kelambatan" adalah masalah umum, memeriksa pg_stat_activity adalah langkah pertama untuk memahami apa yang terjadi. Tampilan pg_stat_activity (dokumentasi untuk setiap kolom dalam tampilan ini dapat ditemukan di sini) berisi baris untuk setiap proses server/koneksi ke database dari klien. Ada beberapa informasi berguna dalam tampilan ini yang dapat membantu.

CATATAN: pg_stat_activity telah diketahui mengubah struktur dari waktu ke waktu, menyempurnakan data yang disajikan. Memahami kolom itu sendiri akan membantu membuat kueri secara dinamis sesuai kebutuhan di masa mendatang.

Kolom penting di pg_stat_activity adalah:

  1. kueri:kolom teks yang menunjukkan kueri yang sedang dieksekusi, menunggu untuk dieksekusi, atau terakhir dieksekusi (bergantung pada statusnya). Ini dapat membantu mengidentifikasi kueri/kueri apa yang mungkin dilaporkan pengembang berjalan lambat.
  2. client_addr:Alamat IP asal koneksi dan kueri ini. Jika kosong (atau Null), itu berasal dari localhost.
  3. backend_start, xact_start, query_start:Ketiganya memberikan stempel waktu kapan masing-masing dimulai. Backend_start menunjukkan kapan koneksi ke database dibuat, xact_start adalah saat transaksi saat ini dimulai, dan query_start adalah saat kueri saat ini (atau terakhir) dimulai.
  4. status:Status koneksi ke database. Aktif berarti sedang menjalankan kueri, 'idle' berarti menunggu masukan lebih lanjut dari klien, 'menganggur dalam transaksi' berarti menunggu masukan lebih lanjut dari klien sambil menahan transaksi terbuka. (Ada yang lain, namun kemungkinannya jarang, lihat dokumentasi untuk informasi lebih lanjut).
  5. namadat:Nama database yang saat ini terhubung dengan koneksi. Di beberapa cluster database, ini dapat membantu mengisolasi koneksi yang bermasalah.
  6. wait_event_type dan wait_event:Kolom ini akan menjadi null saat kueri tidak menunggu, tetapi jika menunggu, kolom ini akan berisi informasi tentang mengapa kueri menunggu, dan menjelajahi pg_locks dapat mengidentifikasi apa yang menunggu. (PostgreSQL 9.5 dan sebelumnya hanya memiliki kolom boolean yang disebut 'menunggu', benar jika menunggu, salah jika tidak.

1.1. Apakah kueri menunggu / diblokir?

Jika ada kueri atau kueri tertentu yang "lambat" atau "bergantung", periksa untuk melihat apakah mereka menunggu kueri lain untuk diselesaikan. Karena penguncian relasi, kueri lain dapat mengunci tabel dan tidak mengizinkan kueri lain untuk mengakses atau mengubah data hingga kueri atau transaksi tersebut selesai.

PostgreSQL 9.5 dan yang lebih lama:

SELECT * FROM pg_stat_activity WHERE waiting = TRUE;

PostgreSQL 9.6:

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL;

PostgreSQL 10 dan yang lebih baru (?):

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL AND backend_type = 'client backend';

Hasil kueri ini akan menampilkan koneksi apa pun yang sedang menunggu koneksi lain untuk melepaskan kunci pada relasi yang diperlukan.

Jika kueri diblokir oleh koneksi lain, ada beberapa cara untuk mengetahui apa itu. Di PostgreSQL 9.6 dan yang lebih baru, fungsi pg_blocking_pids() memungkinkan input ID proses yang diblokir, dan itu akan mengembalikan larik ID proses yang bertanggung jawab untuk memblokirnya.

PostgreSQL 9.6 dan yang lebih baru:

SELECT * FROM pg_stat_activity 
WHERE pid IN (SELECT pg_blocking_pids(<pid of blocked query>));

PostgreSQL 9.5 dan yang lebih lama:

SELECT blocked_locks.pid     AS blocked_pid,
         blocked_activity.usename  AS blocked_user,
         blocking_locks.pid     AS blocking_pid,
         blocking_activity.usename AS blocking_user,
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks 
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

(Tersedia dari Wiki PostgreSQL).

Kueri ini akan mengarah ke apa pun yang memblokir PID tertentu yang disediakan. Dengan itu, keputusan dapat dibuat untuk mematikan kueri pemblokiran atau koneksi, atau membiarkannya berjalan.

Langkah 2 - Jika kueri berjalan, mengapa begitu lama?

2.1. Apakah perencana menjalankan kueri secara efisien?

Jika kueri (atau kumpulan kueri) yang dipermasalahkan berstatus 'aktif', maka kueri tersebut benar-benar berjalan. Jika seluruh kueri tidak tersedia di pg_stat_activity, ambil dari pengembang atau log postgresql dan mulailah menjelajahi perencana kueri.

EXPLAIN SELECT * FROM postgres_stats.table_stats t JOIN hosts h ON (t.host_id = h.host_id) WHERE logged_date >= '2018-02-01' AND logged_date < '2018-02-04' AND t.india_romeo = 569;
Nested Loop  (cost=0.280..1328182.030 rows=2127135 width=335)
  ->  Index Scan using six on victor_oscar echo  (cost=0.280..8.290 rows=1 width=71)
          Index Cond: (india_romeo = 569)
  ->  Append  (cost=0.000..1306902.390 rows=2127135 width=264)
        ->  Seq Scan on india_echo romeo  (cost=0.000..0.000 rows=1 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on juliet victor_echo  (cost=0.000..437153.700 rows=711789 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on india_papa quebec_bravo  (cost=0.000..434936.960 rows=700197 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on two oscar  (cost=0.000..434811.720 rows=715148 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))

Contoh ini memperlihatkan rencana kueri untuk gabungan dua tabel yang juga mengenai tabel yang dipartisi. Kami sedang mencari apa pun yang dapat menyebabkan kueri menjadi lambat, dan dalam hal ini perencana melakukan beberapa Pemindaian Berurutan pada partisi, menunjukkan bahwa mereka kehilangan indeks. Menambahkan indeks ke tabel ini untuk kolom 'india_romeo' akan langsung meningkatkan kueri ini.

Hal-hal yang harus dicari adalah pemindaian sekuensial, loop bersarang, penyortiran yang mahal, dll. Memahami perencana kueri sangat penting untuk memastikan kueri berkinerja sebaik mungkin, dokumentasi resmi dapat dibaca untuk informasi lebih lanjut di sini.

2.2. Apakah tabel yang terlibat membengkak?

Jika kueri masih terasa lambat tanpa perencana kueri menunjuk pada sesuatu yang jelas, saatnya untuk memeriksa kesehatan tabel yang terlibat. Apakah mereka terlalu besar? Apakah mereka kembung?

SELECT n_live_tup, n_dead_tup from pg_stat_user_tables where relname = ‘mytable’;
n_live_tup  | n_dead_tup
------------+------------
      15677 |    8275431
(1 row)

Di sini kita melihat bahwa ada lebih banyak baris mati daripada baris hidup, yang berarti untuk menemukan baris yang benar, mesin harus menyaring data yang bahkan tidak relevan untuk menemukan data nyata. Vakum/vakum penuh pada tabel ini akan meningkatkan performa secara signifikan.

Langkah 3 - Periksa Log

Jika masalah masih tidak dapat ditemukan, periksa log untuk mencari petunjuk.

Pesan FATAL / KESALAHAN:

Cari pesan yang mungkin menyebabkan masalah, seperti kebuntuan atau waktu tunggu yang lama untuk mendapatkan kunci.

Pos pemeriksaan

Semoga log_checkpoints diaktifkan, yang akan menulis informasi pos pemeriksaan ke log. Ada dua jenis pos pemeriksaan, waktunya dan diminta (dipaksa). Jika pos pemeriksaan dipaksa, maka buffer kotor dalam memori harus ditulis ke disk sebelum memproses lebih banyak kueri, yang dapat memberikan sistem basis data perasaan "lambat" secara keseluruhan. Meningkatkan checkpoint_segments atau max_wal_size (bergantung pada versi basis data) akan memberi checkpointer lebih banyak ruang untuk dikerjakan, serta membantu penulis latar mengambil sebagian dari beban penulisan.

Langkah 4 - Bagaimana Kesehatan Sistem Host?

Jika tidak ada petunjuk dalam database itu sendiri, mungkin host itu sendiri kelebihan beban atau mengalami masalah. Apa pun dari saluran IO yang kelebihan beban ke disk, memori yang meluap ke swap, atau bahkan drive yang gagal, tidak satu pun dari masalah ini yang akan terlihat dengan apa pun yang kami lihat sebelumnya. Dengan asumsi database berjalan pada sistem operasi berbasis *nix, berikut adalah beberapa hal yang dapat membantu.

4.1. Beban Sistem

Menggunakan 'atas', lihat rata-rata beban untuk host. Jika jumlahnya mendekati atau melebihi jumlah inti pada sistem, mungkin terlalu banyak koneksi bersamaan yang menghantam database sehingga membuatnya merangkak untuk mengejar ketinggalan.

load average: 3.43, 5.25, 4.85

4.2. Memori Sistem dan SWAP

Menggunakan 'gratis', periksa untuk melihat apakah SWAP telah digunakan sama sekali. Memori yang meluap ke SWAP di lingkungan database PostgreSQL sangat buruk untuk kinerja, dan banyak DBA bahkan akan menghilangkan SWAP dari host database, karena kesalahan 'kehabisan memori' lebih disukai daripada banyak sistem yang lamban.

Jika SWAP sedang digunakan, reboot sistem akan menghapusnya, dan meningkatkan total memori sistem atau mengonfigurasi ulang penggunaan memori untuk PostgreSQL (seperti menurunkan shared_buffers atau work_mem) mungkin dilakukan.

[[email protected] ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7986         225        1297          12        6462        7473
Swap:          7987        2048        5939

4.3. Akses Disk

PostgreSQL mencoba melakukan banyak pekerjaannya di memori, dan menyebarkan penulisan ke disk untuk meminimalkan kemacetan, tetapi pada sistem yang kelebihan beban dengan penulisan yang berat, sangat mudah untuk melihat pembacaan dan penulisan yang berat menyebabkan seluruh sistem melambat saat mengejar pada tuntutan. Disk yang lebih cepat, lebih banyak disk, dan saluran IO adalah beberapa cara untuk meningkatkan jumlah pekerjaan yang dapat dilakukan.

Alat seperti 'iostat' atau 'iotop' dapat membantu menentukan apakah ada hambatan disk, dan dari mana asalnya.

4.4. Periksa Log

Jika semuanya gagal, atau bahkan jika tidak, log harus selalu diperiksa untuk melihat apakah sistem melaporkan sesuatu yang tidak benar. Kami sudah membahas memeriksa postgresql.logs, tetapi log sistem dapat memberikan informasi tentang masalah seperti disk yang gagal, memori yang gagal, masalah jaringan, dll. Salah satu dari masalah ini dapat menyebabkan database bertindak lambat dan tidak dapat diprediksi, jadi pemahaman yang baik kesehatan yang sempurna dapat membantu menemukan masalah ini.

Unduh Whitepaper Hari Ini Pengelolaan &Otomatisasi PostgreSQL dengan ClusterControlPelajari tentang apa yang perlu Anda ketahui untuk menerapkan, memantau, mengelola, dan menskalakan PostgreSQLUnduh Whitepaper

Langkah 5 - Masih Ada Yang Tidak Masuk Akal?

Bahkan administrator yang paling berpengalaman pun akan mengalami sesuatu yang baru yang tidak masuk akal. Di situlah komunitas PostgreSQL global dapat membantu. Sama seperti langkah #0, semakin jelas informasi yang diberikan kepada komunitas, semakin mudah mereka membantu.

5.1. Milis PostgreSQL

Sejak PostgreSQL dikembangkan dan dikelola oleh komunitas open source, ada ribuan orang yang berbicara melalui milis untuk mendiskusikan topik yang tak terhitung jumlahnya termasuk fitur, kesalahan, dan masalah kinerja. Milis dapat ditemukan di sini, dengan pgsql-admin dan pgsql-performance menjadi yang paling penting untuk mencari bantuan terkait masalah kinerja.

5.2. IRC

Freenode menghosting beberapa saluran PostgreSQL dengan pengembang dan administrator di seluruh dunia, dan tidak sulit untuk menemukan orang yang membantu untuk melacak dari mana masalah mungkin berasal. Informasi lebih lanjut dapat ditemukan di halaman PostgreSQL IRC.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara menampilkan nomor baris dalam kueri PostgreSQL?

  2. BERGABUNG (PILIH ... ) pada 1=1?

  3. Menambahkan batasan satu-dari-dua bukan nol di postgresql

  4. Permintaan ILIKE PostgreSQL dengan SQLAlchemy

  5. SQLAlchemy:memfilter nilai yang disimpan dalam daftar bersarang dari bidang JSONB