Sqltunning desde sqlplus

Vamos a volver a la entradas para dummies con un error muy comun.

Uno de los errores mas frecuentes que tenemos desde el enterprise manager es cuando intentamos lanzar el SQL Tuning Advisor sobre una consuta pesada y obtenemos el error

ORA-01555 caused by SQL statement below (SQL ID: g5wg4kxu9m4g3, Query Duration=14163 sec, SCN: 0x09a1.42a95c42):

Este error no nos lo esta dando el advisor en si, sino que es un error del enterprise manager, para poder obtener este advice lo haremos de la siguiente manera

Supongamos que buscamos llevarlo a cabo sobre la SQLID g5wg4kxu9m4g3 y que tenemos identificada esta consulta entre dos snapshots, los 73485 & 73486

Los pasos que debemos de seguir son :

Definimos la tarea


begin_snap  => 73485,
end_snap    =>73486,
sqlidf => g5wg4kxu9m4g3

--create task 
DECLARE
l_sql_tune_task_id  VARCHAR2(100);
BEGIN
l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task (
sql_id=> 'g5wg4kxu9m4g3',
time_limit=> 1500,
task_name=> 'g5wg4kxu9m4g3_tuning_task',
description=> 'Tuning task for statement g5wg4kxu9m4g3',
scope    => DBMS_SQLTUNE.scope_comprehensive
);
   
  DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);
END;
/

Ejecutamos la tarea

EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => 'g5wg4kxu9m4g3_tuning_task');

Obtenemos el resultado

set pagesize 999
set long 65536
set longchunksize 65536
set linesize 200
select dbms_sqltune.report_tuning_task('g5wg4kxu9m4g3_tuning_task') from dual;

Como podemos ver, el uso basico del paquete DBMS_SQLTUNE es extremadamente sencillo

log_archive_dest_1

Hoy vamos a ver una entrada un tanto extraña que me ha ocurrido en alguna base de datos.

A la hora de configurar el archivado, el parametro que tenia era 


alter system set log_archive_dest_1=
'LOCATION=USE_DB_RECOVERY_FILE_DEST,valid_for=(ALL_LOGFILES, ALL_ROLES)';

Sin embargo,  esto fallaba no dejando los archivers en a ubicacion correcta. 

¿como lo solcione?

Algo tan extraño como cambiandolo por una de estas dos maneras 


alter system set log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES, ALL_ROLES)'

alter system set log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST','VALID_FOR=(ALL_LOGFILES, ALL_ROLES)'

Como podeis ver , la diferencia es muy sutil, pero , igual puede servirle a alguien mas

Version del parcheado de la base de datos

Hoy vamos a ver otra de estas entradas para dummies utiles en el dia a dia.
Como sabemos en que version de parcheado nos encontramos?

La primera opcion y mas sencilla es la del uso del binario del sistema operativo opatch, pero , como podemos estar seguros de que el parche/psu se ha ejecutado correctamente y se ha aplicado tambien la parte SQL

Oracle 11g

Si estamos en la version 11g deberemos de hacerlo consultando la tabla del diccionario sys.registry$history

SET LINESIZE 180 PAGESIZE 90 
COLUMN FECHA FORMAT A18
COLUMN action FORMAT A20
COLUMN version FORMAT A10
COLUMN comments FORMAT A30
COLUMN bundle_series FORMAT A10
SELECT TO_CHAR(action_time, 'YYYY-MM-DD HH24:MI') AS FECHA,
       action,
       namespace,
       version,
       comments,
       bundle_series
FROM   sys.registry$history
ORDER by action_time;

Lo que nos devolvera algo similar a :

FECHA              ACTION               NAMESPACE            VERSION    COMMENTS                       BUNDLE_SER
------------------ -------------------- -------------------- ---------- ------------------------------ ----------
07-JAN-2017 15:21  APPLY                SERVER               11.2.0.3   PSU 11.2.0.3.15                PSU
01-DEC-2017 18:59  UPGRADE              SERVER               11.2.0.4.0 Upgraded from 11.2.0.3.0
01-DEC-2017 19:00  APPLY                SERVER               11.2.0.4   PSU 11.2.0.4.171017            PSU

Oracle 12c

Cuando estamos en la version 12c, tendremos dos maneras de encontrar esta informacion:

Preguntando a DBA_REGISTRY_SQLPATCH

La consulta sera muy similar a la anterior, pero en ved de preguntar a el dicionario sys.registry$history, lo haremos a la tabla DBA_REGISTRY_SQLPATCH



SET LINESIZE 180 PAGESIZE 90 
COLUMN FECHA FORMAT A20
COLUMN action FORMAT A10
COLUMN status FORMAT A20
COLUMN description FORMAT A90
COLUMN version FORMAT A10
COLUMN bundle_series FORMAT A10
SELECT TO_CHAR(action_time, 'YYYY-MM-DD HH24:MI:SS') AS action_time,
       action,
       status,
       description,
       version,
       patch_id,
       bundle_series
FROM   sys.dba_registry_sqlpatch
ORDER by action_time;

Lo que nos devolvera algo similar a

ACTION_TIME          ACTION     STATUS     DESCRIPTION                              VERSION      PATCH_ID BUNDLE_SER
-------------------- ---------- ---------- ---------------------------------------- ---------- ---------- ----------
07-MAR-2018 21:37:51 APPLY      SUCCESS    Database Patch Set Update : 12.1.0.2.4  12.1.0.2     20831110 PSU
                                         (20831110)

Mediante el package dbms_qopatch

En la version 12c tenemos el nuevo datapatch en los parcheados, la informacion de los parches de la base de datos esta tambien accesible con el package dbms_qopatch.
Esto ya lo vimos en la entrada Obtener los parches instalados en la base de datos CDB que venia a decir :

 
 set serverout on
exec dbms_qopatch.get_sqlpatch_status;

Lo que nos devuelve

Patch Id : 25171037
        Action : APPLY
        Action Time : 14-JUN-2017 23:09:33
        Description : DATABASE PATCH SET UPDATE 12.1.0.2.170418
        Logfile :
/u01/app/oracle/cfgtoollogs/sqlpatch/25171037/21099266/25171037_apply_SID_2017Jun14_23_09_20.log
        Status : SUCCESS
PL/SQL procedure successfully completed.

Sobre el uso de dbms_qopatch tenemos la URL hay una URL Como saber si un parche esta aplicado en la BBDD que tiene consultas muy utiles para obtener informacion de la base de datos (inventario,paches…)

Esta informacion ha sido obtenido en su totalidad de las URLS:

Restaurando archivelogs

Hoy vamos a volver a las entradas para dummies .
En esta entrada vamos a ver en una entrada muy rapida algunas maneras de restaurar archivelogs.

Desde numero de secuencia

La primera y mas comun recuperar un archiver en conreto

RUN
{
SET ARCHIVELOG DESTINATION TO '/sitiotemporal';
restore archivelog  logseq=8619;
}

Podemos hacerlo tambien con un rango con

restore archivelog from sequence 8619 until sequence 8639;

o tambien con

restore archivelog sequence between 8619 and  8639;

De un dia atras

Esta puede ser muy comoda a la hora de incrementales

RUN
{ 
SET ARCHIVELOG DESTINATION TO '/sitiotemporal';
ALLOCATE CHANNEL d1 DEVICE TYPE disk;
 restore ARCHIVELOG FROM TIME 'SYSDATE-1' UNTIL TIME 'SYSDATE';
}

Tambien podriamos indicarlo

restore ARCHIVELOG FROM TIME "to_date('11/04/18 00:00:01','DD/MM/YY HH24:MI:SS')
UNTIL TIME 'SYSDATE';

En RAC

En un rac es igual que en los anteriores, pero deberemos de indicar el numero de thread que nos corresponde

{
SET ARCHIVELOG DESTINATION TO '/sitiotemporal'
restore archivelog from logseq=8619 until logseq=8632 thread=2;
}

Consultas basicas para lob segments

Hoy vamos a otra de estas entradas para dummies que recopilan SQL utles, en este caso para tratar con los lobs.
Las variables de formateo del sqlplus para estas consultas serian

set linesize 180 pagesize 900
column SEGMENT_NAME format a40;
column TABLE_NAME format a60;
column TABLESPACE_NAME format a30;
column owner format a20;

Lista de los lobs mas grandes y lo que ocupan para el esquema

select  e.owner,l.tablespace_name,
l.table_name,
l.segment_name,sum(e.bytes/(1024*1024*1024)) Gb
from dba_extents e,dba_lobs  l
where
	e.owner = l.owner
	and 	e.segment_name = l.segment_name
	and 	e.OWNER='ESQUEMA'
	and 	e.segment_type = 'LOBSEGMENT'
     group by  
     e.owner,l.tablespace_name,
    l.table_name,
     l.segment_name 
     order by Gb desc ;

Obtener los datos (esquema,tabla y columna) de un LOB determinado

select OWNER,TABLE_NAME,COLUMN_NAME from dba_lobs
 where SEGMENT_NAME='SYS_LOBXXXXXX$$';

Bytes ocupados por un LOB

select sum(dbms_lob.getlength (COLUMNA))/1024/1024 Mb ESQUEMA.TABLA;
o bien 

select bytes/1024/1024 Mb
from dba_segments where segment_name ='SYS_LOBXXXXXX$$' ;

o esta mas completa

set serveroutput on
declare
     l_segment_size_blocks NUMBER;
     l_segment_size_bytes NUMBER;
     l_used_blocks NUMBER;
     l_used_bytes NUMBER;
     l_expired_blocks NUMBER;
     l_expired_bytes NUMBER;
     l_unexpired_blocks NUMBER;
     l_unexpired_bytes NUMBER;
     l_unused_blocks NUMBER;
     l_unused_bytes NUMBER;
     l_non_data_blocks NUMBER;
     l_non_data_bytes NUMBER;
 BEGIN
	DBMS_SPACE.SPACE_USAGE(
   	  segment_owner =>'ESQUEMA',
	  segment_name => 'SYS_LOB0000227238C00034$$',
	  segment_type => 'LOB',
	  segment_size_blocks => l_segment_size_blocks,
	  segment_size_bytes => l_segment_size_bytes,
	  used_blocks => l_used_blocks,
	  used_bytes => l_used_bytes,
	  expired_blocks => l_expired_blocks,
	  expired_bytes => l_expired_bytes,
	  unexpired_blocks => l_unexpired_blocks,
	  unexpired_bytes => l_unexpired_bytes
           );
      l_unused_blocks := l_segment_size_blocks - (l_used_blocks + l_expired_blocks + l_unexpired_blocks);
      l_unused_bytes := l_segment_size_bytes - (l_used_bytes + l_expired_bytes + l_unexpired_bytes);
	  l_non_data_blocks := l_unused_blocks + l_expired_blocks + l_unexpired_blocks;
	  l_non_data_bytes :=  l_unused_bytes + l_expired_bytes + l_unexpired_bytes;
	  DBMS_OUTPUT.ENABLE;
	   DBMS_OUTPUT.PUT_LINE(' Segment Blocks/Bytes   = '||l_segment_size_blocks||' / '||l_segment_size_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Unused Blocks/Bytes    = '||l_unused_blocks||' / '||l_unused_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Used Blocks/Bytes      = '||l_used_blocks||' / '||l_used_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Expired Blocks/Bytes   = '||l_expired_blocks||' / '||l_expired_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Unexpired Blocks/Bytes = '||l_unexpired_blocks||' / '||l_unexpired_bytes);
	  DBMS_OUTPUT.PUT_LINE('===========================================================================');
	  DBMS_OUTPUT.PUT_LINE(' NON Data Blocks/Bytes  = '||l_non_data_blocks||' / '||l_non_data_bytes);
 END;
 /

Mover una tabla con Lobs ( para hacer shrink)

Este metodo implica bloqueo durante el traslado

ALTER TABLE ESQUEMA.TABLA MOVETABLESPACE NUEVOTABLESPACE;
Y para cada uno de los lobs de la tabla 

ALTER TABLE ESQUEMA.TABLA MOVE LOB(COLUMNA) STORE AS SECUREFILE (TABLESPACE NUEVOTABLESPACE);