AWS, RDS

AWS performance insights cli commands

Performance insights subcommands:

  • get-resource-metrics: Returns a time series metric for a set of data sources.
  • describe-dimension-keys: Returns the top offenders for a metric.
  • get-dimension-key-details: Returns the whole sql query. The commands above trimm the queries.
  • list-available-resource-metrics
  • list-available-resource-dimensions

The first step is to obtain the rds instance id, with the name of the instance run:

aws rds describe-db-instances \
  --db-instance-identifier "$DB_NAME" \
  --query 'DBInstances[0].DbiResourceId' \
  --output text

The metrics provided are divided in different categories, os, db, db.sql.stats and db.sql_tokenized.stats. The metrics inside each category can be seen with:

aws pi list-available-resource-metrics \
  --service-type RDS \
  --identifier "$RESOURCE_ID" \
  --metric-types "db"

Get the metric dimensions of each of the db.load metric groups:

aws pi list-available-resource-dimensions \
  --service-type RDS \
  --identifier "$RESOURCE_ID" \
  --metrics "db.load"

Get the top sql queries causing db load

By top offenders:

aws pi describe-dimension-keys \
    --service-type RDS \
    --identifier "$RESOURCE_ID" \
    --start-time "$(date -u -d '3 hours ago' +%Y-%m-%dT%H:%M:%SZ)" \
    --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
    --metric "db.load.avg" \
    --group-by '{"Group":"db.sql","Limit":10}' \
    --output json

Output sample:

{
    "AlignedStartTime": "2026-07-25T16:30:00+02:00",
    "AlignedEndTime": "2026-07-25T19:30:00+02:00",
    "Keys": [
        {
            "Dimensions": {
                "db.sql.db_id": "pi-3805917462",
                "db.sql.id": "VE9KR4CJJM2LGWSQTEGQ8II3O7SSHSAVA0RSNUJJ",
                "db.sql.statement": "WITH MonthlyVisits AS (SELECT d.department_id, d.department_name, DATE_TRUNC('month', a.appointment_date) AS visit_month, COUNT(a.appointment_id) AS total_appointments, COUNT(DISTINCT a.patient_id) AS unique_patients, AVG(EXTRACT(EPOCH FROM (a.check_in_time - a.scheduled_time)) / 60) AS avg_wait_minutes, SUM(CASE WHEN a.status = 'No-Show' THEN 1 ELSE 0 END) AS total_no_shows FROM",
                "db.sql.tokenized_id": "BJDU7AOQG8HI0N15TROYKX9O0UH0DCUM0K4ELEVP"
            },
            "Total": 0.0005631687629059508
        },
        {
            "Dimensions": {
                "db.sql.db_id": "pi-9241085376",
                "db.sql.id": "E87ZK9DIXHBR4T836X04KDJ9X7DICPDQA58MEVSE",
                "db.sql.statement": "WITH TargetYear AS (SELECT 2026 AS reporting_year), MonthlySales AS (SELECT s.store_id, s.store_name, p.category_id, p.category_name, DATE_TRUNC('month', o.order_date) AS sales_month, SUM(oi.quantity * oi.unit_price) AS gross_revenue, SUM(oi.discount_amount) AS total_discounts, COUNT(DISTINCT o.order_id) AS total_orders",
                "db.sql.tokenized_id": "SI4Q2UU56E1FIYL4BKTVI9JXTCAOH44YR3MOEZ70"
            },
            "Total": 0.0002815843814529754
        }
    ]
}

To get the time series data:

aws pi get-resource-metrics \
    --service-type RDS \
    --identifier "$RESOURCE_ID" \
    --metric-queries '[{"Metric":"db.load.avg","GroupBy":{"Group":"db.sql","Limit":10}}]' \
    --start-time "$(date -u -d '3 hours ago' +%Y-%m-%dT%H:%M:%SZ)" \
    --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
    --period-in-seconds 300 \
    --output json

The output of the two previous commands trimms the sql queries, to obtain the whole query use the id from the desired object above and run:

aws pi get-dimension-key-details \
    --service-type RDS \
    --identifier "$RESOURCE_ID" \
    --group db.sql \
    --group-identifier "BJDU7AOQG8HI0N15TROYKX9O0UH0DCUM0K4ELEVP" \
    --requested-dimensions statement \
    --query 'Dimensions[0].Value' \
    --output text | sqlfmt - --single-process -q

Note that the output is piped to sqlfmt to format the query.

Top sql queries by wait

To obtain the top sql queries by wait event, the output can be partitioned:

aws pi describe-dimension-keys \
    --service-type RDS \
    --identifier "$RESOURCE_ID" \
    --start-time "$(date -u -d '3 hours ago' +%Y-%m-%dT%H:%M:%SZ)" \
    --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
    --metric db.load.avg \
    --group-by '{"Group":"db.sql"}' \
    --partition-by '{"Group": "db.wait_event"}'

Find out what is making the db wait

Top offender commands:

aws pi describe-dimension-keys \
  --service-type RDS \
  --identifier "$RESOURCE_ID" \
  --start-time "$(date -u -d '3 hours ago' +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --metric "db.load.avg" \
  --group-by '{"Group": "db.wait_event", "Limit": 10}'

Data series:

aws pi get-resource-metrics \
  --service-type RDS \
  --identifier "$RESOURCE_ID" \
  --start-time "$(date -u -d '3 hours ago' +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --period-in-seconds 60 \
  --metric-queries '[{"Metric":"db.load.avg","GroupBy":{"Group":"db.wait_event","Limit":10}}]'

Links

AWS has more query examples here