SQL tuning in Oracle 11gR2

Oracle utilizza un ottimizzatore SQL molto sofisticato e potente. Questa breve paginetta riporta le indicazioni per sfruttarlo al meglio.

Avevo gia' scritto alcuni documenti sulle novita' dell'ottimizzatore Oracle [NdE novita' della versione 7.3!] e sui principali strumenti di verifica delle prestazioni. Anche se i concetti di base erano sempre gli stessi, sono anche passati quasi 20 anni quindi ho ritenuto opportuno scrivere questo aggiornamento allineato alla versione 11g R2!

Optimizer

L'SQL e' un linguaggio di quarta generazione, ovvero consente di dire cosa si vuole ma non come trovarlo. Gli statement SQL vengono parsificati (che e' una semplice verifica sintattica e sull'accesso ai dati) e quindi vengono analizzati dall'optimizer. L'optimizer ha il compito di decidere quale sia i modo migliore per estrarre i dati richiesti.
L'optimizer Oracle e' cost based, ovvero utilizza statistiche sofisticate sulle tabelle e sugli indici, ed elaborare un plan (piano di esecuzione) ottimizzato per l'SQL utilizzato.

Tutto questo vale in modo praticamente identico da oltre 20 anni, dalla versione 7 di Oracle all'attuale 12c. Ma in realta' di cose in vent'anni ne sono cambiate parecchie.
Per raccontarle tutte servirebbe un'enciclopedia... quindi raccontero' solo il poco che mi interessa e che conosco!

EXPLAIN PLAN, TKPROF, HINT, ANALYZE, ...

Nel bagaglio di esperienze di un DBA Oracle questi tool sono sempre presenti: EXPLAIN PLAN, TKPROF, HINT, ANALYZE!

L'explain plan lo diamo per scontato:

SYS@demo > explain plan for select 1 from dual;

Explained.

SYS@demo > SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1388734953

-----------------------------------------------------------------
| Id  | Operation	 | Name | Rows	| Cost (%CPU)| Time	|
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |	|     1 |     2   (0)| 00:00:01 |
|   1 |  FAST DUAL	 |	|     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------


SYSTEM  = optimizer_features_enable='11.2.0.3'
SESSION = alter session set optimizer_features_enable='11.2.0.3';
SQL     = select /*+ optimizer_features_enable('9.2.0') */

Sul TKPROF non ci sono novita' di rilievo...

Gli HINT sono sempre di piu'. Ovviamente sono una feature non standard di Oracle... ma anche altri RDBMS li stanno imitando.

L'Enterprise Manager fornisce un fracco di informazioni con un'interfaccia grafica semplice. Occorre solo fare attenzione al licensing! [NdA eventualmente impostare il parametro CONTROL_MANAGEMENT_PACK_ACCESS]

I possibili interventi sull'ottimizzatore sono innumerevoli:

select optimizer_feature_enable, count(*)
from v$system_fix_control
group by optimizer_feature_enable 

OPTIMIZER_FEATURE_ENABLE    COUNT(*)
------------------------- ----------
8.0.0				  85
8.1.6				   1
8.1.7				   2
9.2.0				   8
9.2.0.8 			   3
10.1.0				   3
10.1.0.3			   1
10.1.0.4			   1
10.1.0.5			   2
10.2.0.1			   9
10.2.0.2			  12
10.2.0.3			  11
10.2.0.4			  73
10.2.0.5			 111
11.1.0.6			  41
11.1.0.7			  19
11.2.0.1			  68
11.2.0.2			 107
11.2.0.3			  82
11.2.0.4			 141
				  65

http://www.oracle-base.com/articles/misc/sql-trace-10046-trcsess-and-tkprof.php

10053 [NdA DocId 225598.1]

Da ultimo, ma non per importanza, e' necessario ricordare l'ANALYZE: quanti problemi di tuning ha risolto!

SQLT

SQLT (SQLTXPLAIN) e' a mio avviso lo strumento migliore per analizzare gli statement SQL. E' un tool sviluppato individualmente e poi adottato ufficialmente da Oracle. L'installazione e la configurazione sono banali e descritte in modo completo nella documentazione ufficiale [NdA DocId 215187.1].

L'analisi che SQLT effettua e' molto completa e consente di disporre di tutti gli elementi per ottimizzare una query. SQLT puo' essere lanciato con script diversi, con un grado decrescente di funzionalita', a seconda che lo statement SQL sia gia' stato eseguito o meno:

START sqltxtract.sql [SQL_ID]|[HASH_VALUE] [sqltxplain_password]
START sqltxecute.sql script [sqltxplain_password]
START sqltxplain.sql script sqltxplain_password
Da notare l'utility coe_xfr_profile.sql che genera ed importa l'SQL Profile scelto tra quelli analizzati. E' anche possibile utilizzare alcuni trucchi come modificare il force_match o analizzare uno statement con HINT e scambiare i profili... potentissimo!

Un'ultima nota. L'utilizzo di SQLT Profile non richiede le Option DIAGNOSTICS e TUNING pack ma, se assenti, opera in modalita' molto, molto ridotta. coe_xfr_profile richiede il TUNING pack.

Gestione SQL Profile

Il tuning di uno statement SQL puo' richiedere molto tempo e richiede una notevole esperienza... Ma seguendo il seguente esempio e' possibile automatizzare le attivita' di tuning utilizzando un tuning task:

spool analisi_tuning
set lines 180
set long 1000000
SET LONGCHUNKSIZE 1000000
variable report_out clob;
declare
stmt_task VARCHAR2(40);
begin
stmt_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_id => 'xxxyyyzzz');
DBMS_OUTPUT.put_line('task_id: ' || stmt_task );
DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => stmt_task );
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK( stmt_task ) into :report_out FROM dual;
end;
/
print report_out;
spool off

In pratica basta disporre dell'SQL Id dello statement per far provare ad Oracle. Lo script effettua il tuning dello statement e restituisce un report con le diverse alternative di plan. Se si ritiene valida una delle indicazioni emerse basta accettarla come indicato nel report. Ad esempio:

begin
DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(task_name => 'TASK_6969', task_owner => 'SYSTEM', replace => TRUE);
end;
/
Da questo momento e' attivo un nuovo SQL Profile che guida l'ottimizzatore per lo statement analizzato. La verifica dei profile presenti si effettua con:
select * from dba_sql_profiles;

Per disabilitare un profilo si utilizza:

begin
DBMS_SQLTUNE.ALTER_SQL_PROFILE('SQL_PROFILE','STATUS','DISABLED');
end;
/
Per controllare quali statement utilizzano un profile:
set lines 132
column sql_text format a130
select sql_id, child_number, plan_hash_value, sql_profile, EXECUTIONS, ELAPSED_TIME, BUFFER_GETS, sql_text
  from v$sql 
 where sql_profile is not null;

Un'ultima nota. L'utilizzo degli SQL Profile richiede le Option DIAGNOSTICS e TUNING pack.

SPM Baseline

alter system set OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=true sid='*';

spool plan_table
SELECT PLAN_TABLE_OUTPUT
FROM   V$SQL s, DBA_SQL_PLAN_BASELINES b, 
       TABLE(
         DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(b.sql_handle,b.plan_name,'basic') 
       ) t
WHERE  s.EXACT_MATCHING_SIGNATURE=b.SIGNATURE
AND    b.PLAN_NAME=s.SQL_PLAN_BASELINE
AND    s.

alter session set current_schema=them;

Un'ultima nota. L'utilizzo di una baseline SPM richiede l'Edition Enterprise ma non e' necessaria nessuna Option.

DBMS_XPLAN

DECLARE
cl_sql_text CLOB;
BEGIN
SELECT sql_text INTO cl_sql_text from gv$sqlarea where sql_text like 'SELECT name FROM sql_prof_sample_1 t1 JOIN sql_prof_sample_2 t2 ON t1.type_id = t2.type_id WHERE t2.type_name%';
DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text => cl_sql_text, profile => sqlprof_attr('INDEX(@"SEL$1" "T1"@"SEL$1" SQL_PROF_SAMPLE_1_I)'), name => 'SQL_PROF_SAMPLE', force_match => TRUE);
end;
/

Varie ed eventuali...


Titolo: SQL tuning in Oracle 11gR2
Livello: Avanzato (3/5)
Data: 1 Aprile 2014
Versione: 1.0.1 - 1 Aprile 2014
Autore: mail [AT] meo.bogliolo.name