Início / Trilha 4 / Conteúdo / Tópico 4
4

Tuning de SQL

SQL Tuning Advisor, profiles, baselines

📖

Definição

SQL Tuning Advisor

Ferramenta automática que analisa SQL problemático e fornece recomendações concretas: criar índices, atualizar estatísticas, reescrever SQL ou criar SQL Profile.

Como Funciona

1. Analisa estrutura do SQL e estatísticas das tabelas
2. Testa planos alternativos
3. Sugere mudanças com benefício estimado
4. Pode criar SQL Profile automaticamente

SQL Profile vs SQL Plan Baseline

SQL Profile

Fornece informações adicionais ao optimizer (hints invisíveis) sem alterar código SQL. Corrige estimativas erradas de cardinalidade.

  • Não modifica SQL
  • Ajusta estatísticas do optimizer
  • Não garante plano fixo

SQL Plan Baseline

Preserva planos de execução conhecidos como bons. Evita regressões após upgrades ou mudanças de estatísticas.

  • Fixa plano de execução
  • Previne piora de performance
  • Evolutivo: testa planos novos
🛠️

Aplicação Prática

Usando SQL Tuning Advisor

-- Criar tuning task para SQL específico
DECLARE
    l_task_name VARCHAR2(100);
BEGIN
    l_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
        sql_id      => 'g2xb5k8f3zp9n',
        scope       => 'COMPREHENSIVE',  -- ou LIMITED
        time_limit  => 300,              -- segundos
        task_name   => 'TUNE_SQL_g2xb5k8',
        description => 'Tuning query lenta de relatório'
    );
    DBMS_OUTPUT.PUT_LINE('Task: ' || l_task_name);
END;
/

-- Executar a task
EXEC DBMS_SQLTUNE.EXECUTE_TUNING_TASK('TUNE_SQL_g2xb5k8');

-- Ver o report
SET LONG 100000 LONGCHUNKSIZE 100000 PAGESIZE 0
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('TUNE_SQL_g2xb5k8') FROM DUAL;

-- Aceitar recomendação de SQL Profile
EXEC DBMS_SQLTUNE.ACCEPT_SQL_PROFILE('TUNE_SQL_g2xb5k8', 1);

-- Listar SQL Profiles criados
SELECT name, sql_text, status, created
FROM dba_sql_profiles
ORDER BY created DESC;

-- Desabilitar/Habilitar SQL Profile
EXEC DBMS_SQLTUNE.ALTER_SQL_PROFILE('SYS_SQLPROF_01234567', 'STATUS', 'DISABLED');
EXEC DBMS_SQLTUNE.ALTER_SQL_PROFILE('SYS_SQLPROF_01234567', 'STATUS', 'ENABLED');

-- Remover SQL Profile
EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('SYS_SQLPROF_01234567');

Gerenciando SQL Plan Baselines

-- Capturar baseline automaticamente (habilitar captura)
ALTER SYSTEM SET optimizer_capture_sql_plan_baselines = TRUE;

-- Capturar baseline para SQL específico
DECLARE
    l_plans_loaded PLS_INTEGER;
BEGIN
    l_plans_loaded := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(
        sql_id => 'g2xb5k8f3zp9n'
    );
    DBMS_OUTPUT.PUT_LINE('Plans loaded: ' || l_plans_loaded);
END;
/

-- Ver baselines existentes
SELECT
    sql_handle,
    plan_name,
    enabled,
    accepted,
    fixed,
    reproduced,
    origin,
    created
FROM dba_sql_plan_baselines
ORDER BY created DESC;

-- Ver SQL Text de uma baseline
SELECT sql_text
FROM dba_sql_plan_baselines
WHERE plan_name = 'SQL_PLAN_abcd1234';

-- Fixar um plano (impedir mudanças)
DECLARE
    l_plans PLS_INTEGER;
BEGIN
    l_plans := DBMS_SPM.ALTER_SQL_PLAN_BASELINE(
        sql_handle => 'SQL_abc123def456',
        plan_name  => 'SQL_PLAN_abcd1234',
        attribute_name  => 'FIXED',
        attribute_value => 'YES'
    );
END;
/

-- Evoluir baselines (testar planos novos)
DECLARE
    l_report CLOB;
BEGIN
    l_report := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(
        sql_handle => 'SQL_abc123def456'
    );
    DBMS_OUTPUT.PUT_LINE(l_report);
END;
/

-- Remover baseline
DECLARE
    l_plans PLS_INTEGER;
BEGIN
    l_plans := DBMS_SPM.DROP_SQL_PLAN_BASELINE(
        sql_handle => 'SQL_abc123def456',
        plan_name  => 'SQL_PLAN_abcd1234'
    );
END;
/

-- Exportar baselines (para outro banco)
DECLARE
    l_plans PLS_INTEGER;
BEGIN
    l_plans := DBMS_SPM.CREATE_STGTAB_BASELINE(
        table_name => 'SPM_STAGING_TABLE'
    );

    l_plans := DBMS_SPM.PACK_STGTAB_BASELINE(
        table_name => 'SPM_STAGING_TABLE',
        sql_handle => 'SQL_abc123def456'
    );
END;
/

-- Importar baselines
DECLARE
    l_plans PLS_INTEGER;
BEGIN
    l_plans := DBMS_SPM.UNPACK_STGTAB_BASELINE(
        table_name => 'SPM_STAGING_TABLE'
    );
END;
/

SQL Access Advisor (Para Índices)

-- Criar task para recomendar índices
DECLARE
    l_task_id NUMBER;
BEGIN
    DBMS_ADVISOR.CREATE_TASK(
        advisor_name => 'SQL Access Advisor',
        task_name    => 'INDEX_ADVISOR_TASK',
        task_desc    => 'Recomendação de índices para workload'
    );
END;
/

-- Adicionar workload (pode ser AWR, cursor cache, ou SQL específico)
BEGIN
    DBMS_ADVISOR.ADD_STS_REF(
        task_name => 'INDEX_ADVISOR_TASK',
        sts_name  => 'MY_SQL_TUNING_SET'
    );
END;
/

-- Executar análise
EXEC DBMS_ADVISOR.EXECUTE_TASK('INDEX_ADVISOR_TASK');

-- Ver recomendações
SELECT
    rec_id,
    action_type,
    command,
    attr1 AS table_name,
    attr4 AS columns,
    benefit
FROM dba_advisor_actions
WHERE task_name = 'INDEX_ADVISOR_TASK'
ORDER BY benefit DESC;

Resultado Esperado

Executar SQL Tuning Advisor

Criar tasks, interpretar relatórios, aceitar profiles

Gerenciar SQL Profiles

Criar, habilitar/desabilitar, remover profiles

Capturar baselines

Preservar planos bons de queries críticas

Evoluir baselines

Testar e aceitar planos melhores automaticamente

Exportar/importar baselines

Migrar planos entre ambientes

Usar Access Advisor

Recomendar índices para workload

Anterior: Otimização de Índices Próximo: Tuning de Memória