Shell Script to Find Top SQL & PL/SQL Queries and Generate Tuning Reports in Oracle Database from last 24 hrs and Run Tuning advisor automatically
This script will do the following:
✅ Find the top SQL queries executed in the last 24 hours
✅ Identify SQL statements inside PL/SQL blocks
✅ Extract full SQL text for each SQL_ID
✅ Generate a summary report with SQL details
✅ Run
sqltrpt.sql
on each SQL statement✅ Store recommendations in separate tuning reports
📌 Step 1: Create the Shell Script
Save the script as generate_sql_report.sh
:
#!/bin/bash# Set Oracle environment variablesexport ORACLE_SID=yourDBexport ORAENV_ASK=NO. oraenv# Output directoriesREPORT_DIR="/tmp/sql_reports"TUNING_DIR="/tmp/sql_tuning_reports"rm -rf $REPORT_DIR $TUNING_DIRmkdir -p $REPORT_DIR $TUNING_DIRREPORT_FILE="$REPORT_DIR/sql_summary_report.txt"echo "SQL Performance Report - $(date)" > $REPORT_FILEecho "----------------------------------------------------" >> $REPORT_FILE# SQL Query to find top SQL & SQL inside PL/SQL BlocksSQL_QUERY="SET HEADING OFF;SET FEEDBACK OFF;SET PAGESIZE 0;SET TRIMSPOOL ON;SET LINES 200 PAGES 200;COl SQL_ID for a20;COl parsing_schema_name for a20;WITH SQL_INSIDE_PLSQL AS (SELECT DISTINCT sql_id, parsing_schema_name, elapsed_time/1000000 elapsed_sec, buffer_getsFROM v\$sqlWHERE sql_text LIKE '%CUSTOM TEXT SEARCH%'AND last_active_time > SYSDATE - 1AND parsing_schema_name NOT IN ('SYS', 'SYSTEM')AND sql_id IS NOT NULL),TOP_SQL AS (SELECT DISTINCT sql_id, parsing_schema_name, elapsed_time/1000000 elapsed_sec, buffer_getsFROM (SELECT sql_id, parsing_schema_name, elapsed_time, buffer_getsFROM v\$sqlWHERE last_active_time > SYSDATE - 1AND parsing_schema_name NOT IN ('SYS', 'SYSTEM')ORDER BY elapsed_time DESC) WHERE ROWNUM <= 10)SELECT sql_id, parsing_schema_name, elapsed_sec, buffer_gets FROM SQL_INSIDE_PLSQLUNIONSELECT sql_id, parsing_schema_name, elapsed_sec, buffer_gets FROM TOP_SQL;"# Fetch SQL details and store in a temporary fileTMP_SQL_DETAILS="/tmp/sql_details.txt"sqlplus -s / as sysdba <<EOF > "$TMP_SQL_DETAILS"$SQL_QUERYEXIT;EOF# Function to extract SQL text for a given SQL_IDextract_sql_text() {SQL_ID=$1sqlplus -s / as sysdba <<EOF | sed '/^$/d' | sed 's/ */ /g'SET HEADING OFF;SET FEEDBACK OFF;SET PAGESIZE 0;SELECT sql_text FROM v\$sqlWHERE sql_id = '$SQL_ID'AND parsing_schema_name NOT IN ('SYS', 'SYSTEM')AND ROWNUM = 1;EXIT;EOF}# Append header to the reportecho -e "SQL ID | Schema | Elapsed Time (Sec) | Buffer Gets | SQL Text" >> $REPORT_FILEecho "--------------------------------------------------------------------------------------" >> $REPORT_FILE# Process each SQL_ID and generate tuning reportswhile read -r LINE; doSQL_ID=$(echo "$LINE" | awk '{print $1}')SCHEMA_NAME=$(echo "$LINE" | awk '{print $2}')ELAPSED_TIME=$(echo "$LINE" | awk '{print $3}')BUFFER_GETS=$(echo "$LINE" | awk '{print $4}')if [[ -n "$SQL_ID" ]]; thenecho "Processing SQL ID: $SQL_ID"# Extract full SQL textSQL_TEXT=$(extract_sql_text "$SQL_ID")if [[ -z "$SQL_TEXT" ]]; thenSQL_TEXT="SQL Text Not Found"fi# Append SQL details to reportecho -e "$SQL_ID | $SCHEMA_NAME | $ELAPSED_TIME | $BUFFER_GETS | $SQL_TEXT" >> $REPORT_FILE# Run sqltrpt.sql for each SQL IDsqlplus -s / as sysdba <<EOF > "$TUNING_DIR/sqltrpt_$SQL_ID.txt"SET SERVEROUTPUT ONSET LINESIZE 200SET PAGESIZE 500ALTER SESSION SET CURRENT_SCHEMA = SYS;@?/rdbms/admin/sqltrpt.sql$SQL_IDEXIT;EOFecho "Report generated: $TUNING_DIR/sqltrpt_$SQL_ID.txt"fidone < "$TMP_SQL_DETAILS"echo "All SQL & PL/SQL tuning reports are saved in $TUNING_DIR."
📌 Step 2: Make the Script Executable
📌 Step 3: Run the Script
📌 Step 4: Review Reports
- SQL Performance Report (With SQL Text & Execution Details)
- SQL Tuning Reports for Each SQL ID
Post a Comment
Post a Comment