The pg_profile extension collects snapshots of database activity statistics at scheduled intervals and generates HTML performance reports. Use it to identify resource-intensive SQL statements and optimize database performance on ApsaraDB RDS for PostgreSQL.
How it works
pg_profile uses a two-database architecture:
Server database: the database being monitored. It runs pg_stat_statements and pg_stat_kcache to expose query statistics.
Profile database: the database that manages monitoring. It connects to the server database, pulls statistics snapshots via dblink, and stores them locally. You generate performance reports from the profile database.
The profile database and server database can run on the same RDS instance or on separate instances.
Prerequisites
Before you begin, make sure you have:
An ApsaraDB RDS for PostgreSQL instance running PostgreSQL 10 or later
PostgreSQL 17 is not supported.
Minor engine version 20230830 or later. If the instance already has pg_profile installed from an earlier version, it continues to work. To install pg_profile for the first time or reinstall it, update the minor engine version to the latest version.
ImportantTo standardize extension management and protect extension-related data, RDS plans to restrict vulnerable extensions in minor engine version iterations. For details, see [Product changes/Feature changes] Limits on extension creation for ApsaraDB RDS for PostgreSQL instances.
A privileged account on the instance
Usage notes
pg_profile requires pg_stat_statements. Install it before pg_profile. Optionally, also install pg_stat_kcache to collect kernel-level I/O statistics.
Snapshots consume disk space. pg_profile includes an automatic cleanup mechanism—monitor disk usage and adjust retention settings as needed.
Each snapshot takes time to complete. Collect snapshots once or twice per hour.
Install and uninstall pg_profile
Run the following statements using a privileged account:
-- Install
CREATE EXTENSION pg_profile;
-- Uninstall
DROP EXTENSION pg_profile;Set up monitoring
This section walks through setting up a server database named server and a profile database named profile on the same RDS instance. The same steps apply when the databases are on separate instances—only the connection parameters differ.
Set up the server database
Run the following statements using a privileged account.
Create the server database.
CREATE DATABASE server;Connect to the server database and install the required extensions.
Both pg_stat_statements and pg_stat_kcache must be loaded at database startup. Add both to the shared_preload_libraries parameter before creating these extensions. pg_stat_kcache depends on pg_stat_statements, so both must be present in shared_preload_libraries. For instructions, see Set parameters.
\c server CREATE EXTENSION pg_stat_statements; CREATE EXTENSION pg_stat_kcache;Verify the extensions are installed.
\dxExpected output:
Name | Version | Schema | Description --------------------+---------+------------+------------------------------------------------------------------------ pg_stat_kcache | 2.2.1 | public | Kernel statistics gathering pg_stat_statements | 1.9 | public | track planning and execution statistics of all SQL statements executed ...
Set up the profile database
Run the following statements using a privileged account.
Create the profile database.
CREATE DATABASE profile;Connect to the profile database and install the required extensions.
\c profile CREATE EXTENSION plpgsql; CREATE EXTENSION dblink; CREATE EXTENSION pg_profile;Verify the extensions are installed.
\dxExpected output:
Name | Version | Schema | Description ------------+---------+------------+-------------------------------------------------------------- dblink | 1.2 | public | connect to other PostgreSQL databases from within a database pg_profile | 4.0 | public | PostgreSQL load profile repository and report builder plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language ...
Register the server database connection
From the profile database, register the server database as a monitoring target. Run the following statement using a privileged account.
SELECT create_server('server', 'host=<host> dbname=server port=<port> user=<user> password=<password>');| Parameter | Example | Description |
|---|---|---|
host | 127.0.0.1 | Endpoint of the RDS instance where the server database runs. See the table below for values by network topology. |
dbname | server | Name of the server database. |
port | 3002 | Port of the RDS instance where the server database runs. Run SHOW PORT; to get the port. |
user | test_user | Privileged account username for the server database instance. |
password | T123456! | Password of the account. |
`host` values by network topology:
| Topology | Value for host |
|---|---|
| Same RDS instance | 127.0.0.1 |
| Different instances, same virtual private cloud (VPC) | Internal endpoint of the server database instance |
| Different instances, different VPCs | Public endpoint of the server database instance. The profile database instance must be configured with a NAT gateway and a public IP address. |
To get the internal and public endpoints of an instance, see View and modify the endpoint and port number of an instance.
Expected output:
show_servers
---------------------------------------------------------------------------------------
(local,"dbname=profile port=3002",t,)
(server,"host=127.0.0.1 dbname=server port=3002 user=test_user password=****",t,)
(2 rows)Creating a server connection also creates a local connection representing the profile database itself. You can see it in the output above.Configure the profile database connection
After the local connection is created, configure its credentials. Run the following statement using a privileged account.
SELECT set_server_connstr('local','host=127.0.0.1 dbname=profile port=<port> user=<user> password=<password>');| Parameter | Example | Description |
|---|---|---|
host | 127.0.0.1 | Set to 127.0.0.1. |
dbname | profile | Name of the profile database. |
port | 3002 | Port of the profile database instance. Run SHOW PORT; to get the value. |
user | test_user | Privileged account username for the profile database instance. |
password | T123456! | Password of the account. |
Collect snapshots and generate reports
Collect a snapshot
From the profile database, run take_sample() to collect a snapshot from all registered servers. Use a privileged account.
SELECT take_sample();Expected output:
take_sample
-------------------------
(server,OK,00:00:00.52)
(local,OK,00:00:00.51)
(2 rows)Collect at least two snapshots before generating a report—the report covers the activity between two snapshot points.
View collected snapshots
SELECT * FROM show_samples('server');Example output:
sample | sample_time | sizes_collected | dbstats_reset | bgwrstats_reset | archstats_reset
--------+------------------------+-----------------+---------------+-----------------+-----------------
1 | 2022-09-30 02:14:07+00 | t | | |
2 | 2022-09-30 02:16:59+00 | t | | |
3 | 2022-09-30 02:17:58+00 | t | | |Generate a report
A report covers the activity between two snapshots—specify the start and end sample numbers.
Option 1: From psql in the profile database
\o report_2_3.html
SELECT get_report('server',2,3);Option 2: From the command-line interface (CLI)
psql -Aqtc "SELECT profile.get_report('server',2,3)" \
-o report_server_2_3.html \
-d profile \
-h <endpoint of the profile database instance> \
-p 5432 \
-U <privileged account of the profile database instance>Both methods export the report as an HTML file to your local machine.
Automate snapshot collection
Use pg_cron to run take_sample() on a schedule. Collect snapshots once or twice per hour to capture meaningful intervals without generating excessive data.