Jugando con las estadisticas de un esquema

Hoy vamos a ver algunas consultas practicas de las estadisticas de sistema

Esquemas o objetos de un esquema con las estadisticas bloqueadas

Veamos algunas consultas utiles para comprobar cuales son las tablas que estan bloqueadas o para trabajar con las estadistias del esquema APPSCHEMA

Tablas conlas estadisticas bloqueadas para un esquema


select owner, table_name, stattype_locked
from dba_tab_statistics
where
stattype_locked is not null and OWNER=’APPSCHEMA’;

Cuando fueron bloqueadas las estadisticas en estas tablas?


set linesize 200
set pagesize 0
col owner format a20;
col table_name format a30;
Select table_name,last_analyzed from dba_tables
where table_name in
(select table_name from dba_tab_statistics where stattype_locked is not null and OWNER=’APPSCHEMA’)
order by last_analyzed asc ;

Tenemos una metaconsulta para desbloquearlas todas?

  select 'exec dbms_stats.unlock_table_stats('||chr(39)||'APPSCHEMA'||chr(39)||','||chr(39)||TABLE_NAME||chr(39)||' );'
       from dba_tab_statistics where stattype_locked is not null and OWNER='APPSCHEMA';

Ver las fechas de las estadisticas que han sido analizadas en los ultimos 2 dias

set pagesize 9000;
column owner format a20;
column TABLE_NAME format a30;
column PARTITION_NAME format a30;
select owner,table_name,partition_name,to_char(LAST_ANALYZED,'dd-mm-yy hh:mi'),NUM_ROWS,STATTYPE_LOCKED from dba_TAB_STATISTICS
where OWNER='APPSCHEMA' 
and LAST_ANALYZED  < sysdate-2
order by LAST_ANALYZED asc ;

Ver la fecha en la que fueron obtenidas las estadisticas de una tabla en concreto

set pagesize 9000;
column owner format a20;
column TABLE_NAME format a30;
column PARTITION_NAME format a30;
select owner,table_name,partition_name,to_char(LAST_ANALYZED,'dd-mm-yy hh:mi'),NUM_ROWS,STATTYPE_LOCKED from dba_TAB_STATISTICS
where TABLE_NAME='APPSCHEMA' 
order by LAST_ANALYZED asc ;

Como salvamos las estadisticas de un determinado esquema

Creamos una tabla de estadisticas llamada «MISTATS bajo el esquema APPSCHEMA

exec dbms_stats.create_stat_table(ownname => 'APPSCHEMA', stattab => 'MISTATS');

Si quisiesemos guardar solo las estadisticas de una tabla

  
exec dbms_stats.export_table_stats(ownname=>'APPSCHEMA', tabname=>'MISTATS', statown=>'APPSCHEMA', stattab=>'MISTATS', cascade=>true);

Si queremos salvar los de un esquema

EXEC DBMS_STATS.export_schema_stats('APPSCHEMA','MISTATS',NULL,'APPSCHEMA');

Mas informacion en

Formatear el prompt del SQLplus

Hoy vamos a ver una entrada muuy sencilla de como formatear el prompt de SQLPLUS
Bajo nuestro oracle home tenemos un fichero llamado glogin.sql donde podemos definir las variables del sqlplus, entre ellas el prompt.
Supongaamos que queremos saber cual es el usuario con el que nos conectamos, seria tan sencillo como aniadir la linea

dbserver01:vi /u01/app/oracle/product/19c/dbhome_1/sqlplus/admin/glogin.sql
--
-- Copyright (c) 1988, 2005, Oracle.  All Rights Reserved.
--
-- NAME
--   glogin.sql
--
-- DESCRIPTION
--   SQL*Plus global login "site profile" file
--
--   Add any SQL*Plus commands here that are to be executed when a
--   user starts SQL*Plus, or uses the SQL*Plus CONNECT command.
--
-- USAGE
--   This script is automatically run
--
def _editor=vi
set timing on
set feedback on
set sqlprompt "_user  _connect_identifier > "

Ms informacion, en:

  • https://www.youtube.com/watch?v=Ax4s39KfcZ8
  • https://www.oreilly.com/library/view/oracle-sqlplus-the/0596007469/re95.html

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

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);

Uptime de una base de datos Oracle

Hoy vamos a volver con una nueva entrada para muy dummies.

Como averiguamos hace cuanto tiempo esta la base de datos levantada?

Podemo usar alguna de estas consultas

select instance_name,
to_char(startup_time,'mm/dd/yyyy hh24:mi:ss') as startup_time 
from v$instance;

O si asumimos que es cuando arranco el pmon

SELECT database_name, 
TO_CHAR(logon_time, 'DD-MM-YYYY HH24:MI:SS') 
FROM v$session WHERE program LIKE '%PMON%';

O como siempre, podemos buscar que nos dicen en Burleson colsulting

select 
   'Hostname : ' || host_name
   ,'Instance Name : ' || instance_name
   ,'Started At : ' || to_char(startup_time,'DD-MON-YYYY HH24:MI:SS') stime
   ,'Uptime : ' || floor(sysdate - startup_time) || ' days(s) ' ||
   trunc( 24*((sysdate-startup_time) - 
   trunc(sysdate-startup_time))) || ' hour(s) ' ||
   mod(trunc(1440*((sysdate-startup_time) - 
   trunc(sysdate-startup_time))), 60) ||' minute(s) ' ||
   mod(trunc(86400*((sysdate-startup_time) - 
   trunc(sysdate-startup_time))), 60) ||' seconds' uptime
from 
   sys.v_$instance;