
Alat ini ditulis karena minat olahraga ketika saya menemukan bahwa tampilan pg_stat_activity di PostgreSQL 10 memiliki bidang wait_event_type dan wait_event, yang intinya sangat mirip dengan wait_class dan acara dari sesi v $.
Bekerja aktif dengan
program ASH-Viewer
akardapolov saat ini, saya penasaran betapa sulitnya untuk menulis ulang produk ini di bawah Postgres. Mengingat bahwa saya bukan pengembang profesional, itu tidak mudah, tetapi sangat menarik. Dalam prosesnya, saya bahkan menemukan, bagi saya, beberapa bug signifikan yang muncul dalam program asli untuk Oracle, serta untuk Edisi Standar.
Prinsip-prinsip PASH-Viewer:
Tidak perlu ekstensi. Kami mengambil data secara eksklusif dari tampilan pg_stat_activity internal.
Sekali sedetik, permintaan dibuat untuk sesi aktif:
teks permintaan pg_stat_activitySELECT current_timestamp, datname, pid, usesysid, usename, application_name, backend_type, coalesce(client_hostname, client_addr::text, 'localhost') as client_hostname, wait_event_type, wait_event, query, query_start, 1000 * EXTRACT(EPOCH FROM (clock_timestamp()-query_start)) as duration from pg_stat_activity where state='active' and pid != pg_backend_pid();
Sekali setiap 15 detik, data untuk 15 gambar terakhir dirata-rata dan ditampilkan pada grafik.
Id SQL yang diperlukan untuk mengelompokkan pertanyaan di bagian SQL Top, saya membuat sendiri, itu tidak ada hubungannya dengan queryid dari pg_stat_statements. Saya sedang berpikir bagaimana cara menggunakan queryid, tapi sayangnya saya tidak menemukan cara untuk mencocokkan permintaan dari dua tampilan ini. Akan lebih bagus jika pengembang menambahkan bidang queryid ke pg_stat_activity.
SQL id = 13 karakter pertama dari md5 (teks kueri yang dinormalisasi).
Teks kueri yang dinormalisasi adalah kueri di mana karakter baris baru dan ruang tambahan dihapus, dan literal diganti dengan $ 1, $ 2, dll ... Sulit bagi saya untuk menulis fungsi normalisasi permintaan yang bagus. Saya menulis yang buruk. Saya mengutip teksnya, tapi tolong jangan melihatnya, kalau tidak saya malu. Lebih baik kirim yang bagus.
Menormalkan SQL public static String NormalizeSQL(String sql) { sql = sql.replaceAll("\\n", " "); sql = sql.replaceAll("\\(", " ( "); sql = sql.replaceAll("\\)", " ) "); sql = sql.replaceAll(",", " , "); sql = sql.replaceAll("'", " ' "); sql = sql.replaceAll("=", " = "); sql = sql.replaceAll("<", " < "); sql = sql.replaceAll(">", " > "); sql = sql.replaceAll(";", ""); sql = sql.replaceAll("[ ]+", " "); sql = sql.replaceAll("> =", ">="); sql = sql.replaceAll("< =", "<="); sql = sql.toLowerCase().trim(); String[] array = sql.split(" ", -1); int var_number = 0; String normalized_sql = ""; Boolean quote_flag = false; for (int i = 0; i < array.length; i++) { if (array[i].equals("'")) { if (!quote_flag) { quote_flag = true; var_number++; normalized_sql += "$" + var_number + " "; } else { quote_flag = false; } } else if (quote_flag) { continue; } else if (array[i].matches("-?\\d+(\\.\\d+)?")) { var_number++; normalized_sql += "$" + var_number + " "; } else if (array[i].equals("order")) { for (int j = i; j < array.length; j++) { normalized_sql += array[j] + " "; } return normalized_sql.trim(); } else { normalized_sql += array[i] + " "; } } return normalized_sql.trim(); }
Sulit untuk menyelesaikan rencana eksekusi permintaan. Kepada Oracle Anda datang dan berkata, "Beri saya rencana untuk sqlid = ...", dan dia menjawab Anda - "Apakah Anda punya yang terbaru, atau kemarin, atau menunjukkan segalanya untuk bulan lalu dengan statistik eksekusi untuk masing-masing?" Dan PostgreSQL menjawab Anda - "Apa itu sqlid?"
Oleh karena itu, untuk pertanyaan dari formulir SELECT / UPDATE / INSERT / DELETE, kami mengirim perintah EXPLAIN ke database dan menyimpan hasilnya secara lokal. Kami melakukan ini tidak lebih dari 1 kali per jam. Selama debugging, ditemukan bahwa EXPLAIN menggantung pada kunci dengan cara yang sama seperti permintaan itu sendiri akan menggantung, yang ingin kita ketahui rencananya. Karena itu, saya harus menambahkan setQueryTimeout (1).
Dan ini hanya berfungsi jika permintaan dieksekusi dalam database yang sama dengan yang Anda sambungkan (ditunjukkan saat mengkonfigurasi koneksi). Dan hanya jika Anda terhubung ke database di bawah superuser (postgres), yang beberapa mungkin takut. Karena itu, Anda dapat membuat pengguna khusus untuk pemantauan. Semuanya kecuali tampilan rencana akan berfungsi.
CREATE USER pgmonuser WITH password 'pgmonuser'; GRANT pg_monitor TO pgmonuser;
Unduh dari GitHub:
https://github.com/dbacvetkov/PASH-Viewer/releasesUPD:Dalam versi 0.3, ia menambahkan dukungan untuk PostgreSQL 9.6 (hanya ada dua kelas menunggu - Lock dan LWLock, semuanya berjalan seperti "CPU") dan PostgreSQL 9.4 - 9.5 (ada CPU atau Lock yang menunggu secara umum).
Dalam versi 0.3.1, menambahkan bidang Jenis Backend di Sesi Top dan menyingkirkan bilah putih pada grafik.
Dalam versi 0.3.2, peningkatan kerja dengan rencana, menambahkan beberapa statistik tentang permintaan (Durasi AVG, Panggilan Panggilan) dan kemampuan untuk melihat data historis:
Cara-membuat-pg_stat_activity-historical-table .
Terima kasih dan salam:
Alexander Kardapolov untuk ASH-Viewer.
Anton Glushakov untuk konsultasi dan pengujian.
Dmitry Rudopysov untuk menjelaskan cara mengkompilasi dan menjalankan proyek yang diunduh dari github.
Lebih banyak slide:


