7.1 EL REPORTE AWR
·
Generar el reporte AWR
- El
AWR realiza la recolección de datos estadísticos y de rendimiento de una base
de datos Oracle que incluye:
- Eventos Wait usados para identificar
problemas de rendimiento.
- Estadísticas de Sistema y sesiones.
- Estadísticas de uso de objetos.
- Estadísticas de sentencias SQL, Select,
Insert, etc.
- Por defecto Oracle AWR realiza la recolección
de datos cada hora con una retención de 7 días
Desde sqlplus se ejecuta el siguiente script:
SQL>@$ORACLE_HOME/rdbms/admin/awrrpt.sql (en Linux,
AIX, Solaris)
En la
ruta donde está ubicado se genera un archivo.
Si la
base de datos tiene varios incarnation
SQL>@$ORACLE_HOME/rdbms/admin/awrrpti.sql
Nota:
En caso de que los pack DIAGNOSTIC Y TUNING de la base de datos se encuentren
deshabilitados, no se capturaran datos para este informe.
7.2 SOBRE LOS CURSORES
Una de las
mayores dificultades para la base de datos es el volumen de cursores abiertos
en la ejecución de sentencias, esto puede radicar en una mala práctica del
código de la aplicación que ejecuta las sentencias.
Estas
son algunas consultas sobre los cursores.
select user_name,
status, osuser, machine, C.SQL_FULLTEXT
from v$session b,
v$open_cursor a, V$SQLAREA c
WHERE A.SID = b.SID
and C.ADDRESS =
a.ADDRESS
and
status='INACTIVE' ;
select a.value,
s.username, s.sid, s.serial#
from v$sesstat a,
v$statname b, v$session s
where a.statistic#
= b.statistic# and s.sid=a.sid
and b.name =
'opened cursors current';
select
sum(a.value),username
from v$sesstat a,
v$statname b, v$session s
where a.statistic#
= b.statistic# and s.sid=a.sid
and b.name =
'opened cursors current'
group by username;
select max(a.value)
as highest_open_cur, p.value as max_open_cur
from v$sesstat a,
v$statname b, v$parameter p
where a.statistic#
= b.statistic#
and b.name =
'opened cursors current'
and P.name= 'open_cursors'
group by p.value;
SELECT s.osuser,
s.username, s.sid, count(*)
FROM v$session s, v$open_cursor oc
WHERE s.saddr = oc.saddr AND
S.USERNAME is not null
group by S.OSUSER, S.USERNAME, S.sid;
SELECT *
FROM V$PARAMETER
where name like
'%curso%';
7.3 OBJETOS INVALIDOS
· La
siguiente sentencia permite hacer un conteo de todos los objetos en estado inválido
en la base de datos sin importar el esquema propietario.
SQL> select
COUNT(*) from dba_objects where status='INVALID';
La siguiente sentencia suministra la información del Esquema, nombre y tipo de objeto que se encuentra en estado Inválido.
SQL> select
owner,object_name,object_type,status from dba_objects
where status='INVALID';
· Es posible
con un scripts que trae la base de datos realizar un proceso de recompilación
automática, únicamente los objetos que no tengan errores quedaran en estado valido.
Este proceso se ejecuta desde la consola.
7.3.1 LAS FUNCIONES Y
PROCEDIMIENTOS DES-COMPILADOS
La
siguiente sentencia dinámica genera los scripts pertinentes para compilar los
objetos de tipo Función o Procedimiento.
SQL>select
'alter '||object_type||' '||owner||'.'||object_name||' compile;'
from dba_objects
where
status='INVALID'
and object_type
in('FUNCTION','PROCEDURE');
7.3.2 LOS OBJETOS DE TIPO PACKAGE
· La siguiente
sentencia dinámica genera los scripts pertinentes para compilar los objetos de
tipo Package.
SQL>select
'alter '||object_type||' '||owner||'.'||object_name||' compile;'
from dba_objects
where
status='INVALID'
and object_type
in('PACKAGE')
La siguiente sentencia dinámica genera los scripts pertinentes para compilar los objetos de tipo Package Body.
SQL>select
'alter package '||owner||'.'||object_name||' compile body;'
from dba_objects
where
STATUS='INVALID'
and object_type in('PACKAGE
BODY');
7.3.3 LOS triggers en estado disable
·
La
siguiente sentencia extrae los Triggers que se encuentran en estado DISABLE.
SQL>select
t.OWNER,t.TRIGGER_NAME,t.TABLE_NAME,t.TRIGGER_TYPE
from dba_triggers t
where
status='DISABLED'
and owner not in
('SYS','SYSTEM','SCOTT','AURORA$JIS$UTILITY$','AURORA$ORB$UNAUTHENTICATED','OLAPDBA','OLAPSYS','OLAPSVR',
'ORDPLUGINS','ORDSYS','OSE$HTTP$ADMIN','OUTLN','PUBLIC','QS','QS_ADM','QS_CB','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS',
'RMAN','SH','WKSYS','CTXSYS','MDSYS','OE','WMSYS','DBSNMP','ANONYMOUS','XDB','TRACESVR','DIP','DMSYS','EXFSYS','MDDATA',
'MGMT_VIEW','ORACLE_OCM','SI_INFORMTN_SCHEMA','SYSMAN','TSMSYS');
Para
habilitar los trigger se puede usar la siguiente sentencia dinámica la cual
activa los triggers.
SQL> select 'ALTER
TRIGGER ' || OWNER || '.' || t.TRIGGER_NAME || ' ENABLE;'
from dba_triggers t
where
status='DISABLED'
and owner in
('USUARIO');
7.3.4 LOS TRIGGERS EN ESTADO INVÁLIDO
· Existe una
forma para compilar los trigger de forma manual, para ello se debe tener el
propietario del trigger y el nombre del mismo.
SQL>select
owner,object_name,object_type,status FROM DBA_OBJECTS WHERE
STATUS='INVALID' AND OBJECT_TYPE ='TRIGGER';
y luego de forma manual se ejecuta la siguiente sentencia.
SQL>EXEC DBMS_DDL.alter_compile (' TIPE_OBJETO ', ' SQUEMA ', ‘NOMBRE
TRIGGER’);
O
SQL> alter trigger “OWNER.TRIGGER"
compile;
·
La
siguiente sentencia dinámica genera los scripts pertinentes para compilar los
objetos de tipo TRIGGER que se encuentran en estado INVALIDO
SQL> select 'EXEC
DBMS_DDL.alter_compile ('||OBJECT_TYPE||','||OWNER||','||OBJECT_NAME||');'FROM
DBA_OBJECTS WHERE STATUS='INVALID' AND OBJECT_TYPE ='TRIGGER';
7.3.5 LOS SINONIMOS INVALIDOS
· La
siguiente sentencia extrae los scripts de los SINONIMOS que se encuentran en
estado INVALIDO.
SQL> select 'alter public synonym
'||object_name||' compile;' from all_objects where status='INVALID' and
object_type='SYNONYM';
Al
persistir el estado de INVALIDO del sinónimo es necesario recrearlo.
SQL> SELECT 'CREATE OR REPLACE SYNONYM "'||OB.OWNER||'"."'||OB.OBJECT_NAME||'"
FOR "'||DB.TABLE_OWNER||'"."'||DB.TABLE_NAME||'";'FROM
DBA_OBJECTS OB, DBA_SYNONYMS DB WHERE OB.OWNER = DB.OWNER AND OB.OBJECT_NAME =
DB.SYNONYM_NAME AND OB.STATUS='INVALID' AND OB.OBJECT_TYPE ='SYNONYM';
7.3.6 LOS CONSTRAINT EN ESTADO
INACTIVO
La
siguiente sentencia permite validar los constraint que se encuentran en estado
inactivo. Suministra la información del Esquema, nombre del constraint, tipo,
tabla, estado y fecha de modificación.
SQL>SELECT owner,constraint_name, decode(constraint_type, 'C', 'Check', 'O', 'R/O View', 'P', 'Primary', 'R', 'Foreign', 'U', 'Unique', 'V', 'Check view') type, table_name, status, last_change FROM DBA_CONSTRAINTS WHERE STATUS='DISABLED' and owner not in ('SYS','SYSTEM','SCOTT','AURORA$JIS$UTILITY$','AURORA$ORB$UNAUTHENTICATED','OLAPDBA','OLAPSYS','OLAPSVR', 'ORDPLUGINS','ORDSYS','OSE$HTTP$ADMIN','OUTLN','PUBLIC','QS','QS_ADM','QS_CB','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS', 'RMAN','SH','WKSYS','CTXSYS','MDSYS','OE','WMSYS','DBSNMP','ANONYMOUS','XDB','TRACESVR','DIP','DMSYS','EXFSYS','MDDATA', 'MGMT_VIEW','ORACLE_OCM','SI_INFORMTN_SCHEMA','SYSMAN','TSMSYS');
La siguiente
sentencia dinámica genera los scripts para modificar el estado de los
constraint que presentan estado DISABLE cambiándolo a ENABLE.
SELECT 'alter table ' ||
owner || '.' || table_name || ' enable constraint ' || constraint_name || ';' FROM
DBA_CONSTRAINTS WHERE
STATUS='DISABLED' and owner not in
('SYS','SYSTEM','SCOTT','AURORA$JIS$UTILITY$','AURORA$ORB$UNAUTHENTICATED','OLAPDBA','OLAPSYS','OLAPSVR', 'ORDPLUGINS','ORDSYS','OSE$HTTP$ADMIN','OUTLN','PUBLIC','QS','QS_ADM','QS_CB','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS', 'RMAN','SH','WKSYS','CTXSYS','MDSYS','OE','WMSYS','DBSNMP','ANONYMOUS','XDB','TRACESVR','DIP','DMSYS','EXFSYS','MDDATA', 'MGMT_VIEW','ORACLE_OCM','SI_INFORMTN_SCHEMA','SYSMAN','TSMSYS');
7.3.7 VALIDACIÓN DE INDICES
- La consulta
extrae todos los índices de la base de datos que se encuentran en estado
UNUSABLE
SQL> select * from dba_indexes where status='UNUSABLE';
-
La consulta
extrae todos los índices particionados de la base de datos que se encuentran en
estado UNUSABLE
SQL>select *
from dba_ind_PARTITIONS where
status='UNUSABLE'
- Sentencia
dinámica que genera los scripts para la re-creación de los índices en estado
Unusable.
SQL> select
'ALTER INDEX ' || OWNER || '.' || INDEX_NAME || ' REBUILD;' from dba_indexes where
STATUS='UNUSABLE' union select 'ALTER INDEX
' || INDEX_OWNER || '.' || INDEX_NAME || ' REBUILD PARTITION ' ||
PARTITION_NAME || ';' from
dba_ind_partitions where
STATUS='UNUSABLE' union select 'ALTER INDEX
' || INDEX_OWNER || '.' || INDEX_NAME || ' REBUILD SUBPARTITION ' ||
PARTITION_NAME || ';' from
dba_ind_subpartitions where STATUS='UNUSABLE';
-
MOVER INDICES A
DETERMINADO TABLESPACE
El
script dinámico genera la sintaxis de las sentencias que se deben ejecutar para
mover los indices a otro tablespace.
Se
debe incluir el nombre del tablespace destino de los índices, el Esquema dueño
de los indices a mover y el nombre del tablespace en el cual se encuentran los
índices que serán movidos.
SQL>select
'alter index ' || owner || '.' || index_name || ' rebuild tablespace PROVEEDORES_INDX_32K;' from dba_indexes where owner in
('PROVEEDORES_13') and
tablespace_name='PROVEEDORES_13';
SQL>SELECT
'alter index ' || owner || '.' || segment_name || ' rebuild tablespace
GIPS_IDX;' FROM DBA_SEGMENTS WHERE OWNER='GIPS' AND SEGMENT_TYPE='INDEX' AND
TABLESPACE_NAME='USERS';
7.3.8 COMPILAR LOS OBJETOS DE UN
ESQUEMA
·
La siguiente
sentencia permite compilar todos los
objetos inválidos de un ESQUEMA específico, se debe digitar el nombre del
esquema.
SQL> exec
dbms_utility.compile_schema('NOMBRE_ESQUEMA'); (ejecutar con sys)
Cabe anotar que este procedimiento toma
bastante tiempo su ejecución y es necesario tener bloqueados todos los accesos
a la base de datos.
7.3.9 COMPILAR Las vistas
materializadas INVÁLIDAS
· La siguiente
sentencia dinámica genera los scripts para la re-compilación de las vistas
materializadas en estado INVALID.
SQL>select 'alter materialized
view '||owner||'.'||object_name|| ' compile;' from all_objects where
status='INVALID' and object_type='MATERIALIZED VIEW';
7.3.10 COMPILAR Las vistas invalidas
· La siguiente
sentencia dinámica genera los scripts para la re-compilación de las vistas en
estado INVALID.
SQL>select 'alter view
'||owner||'.'||object_name|| ' compile;' from all_objects where status='INVALID'
and object_type='VIEW';
7.3.11 COMPILAR OBJETOS DE JAVA
CLASS INVÁLIDOS
· La siguiente
sentencia dinámica genera los scripts para la re-compilación de los
objetos JAVA CLASS cuyo estado es
INVALID.
SQL>Select 'alter java class
"'||object_name||'" compile;' from user_objects where status <>
'VALID' And object_type ='JAVA CLASS';
7.4 SOBRE ESTADÍSTICAS
·
Estadísticas
de acceso a datos.
-
Con los
siguientes comandos se pueden realizar la captura de estadísticas para algunos
objetos de la base de datos.
A)
Captura de
estadísticas en tablas, ejemplos
SQL>exec
dbms_stats.gather_table_stats(ownname => 'USUARIO', tabname => 'NOMBRE_TABLA');
B)
Captura de
estadísticas en índices, ejemplos
SQL>exec
dbms_stats.gather_index_stats(ownname => 'USUARIO', indname =>
'NOMBRE_INDICE');
C)
Es posible
actualizar las estadísticas de un esquema específico completo.
SQL>exec
DBMS_STATS.gather_schema_stats('USUARIO');
D)
Actualizar
estadísticas de la base de datos completa
SQL>exec
DBMS_STATS.GATHER_DATABASE_STATS;
-
Si después
de tomar las estadísticas se presentan problemas es posible eliminar las
estadísticas tomadas
i)
Eliminación
de estadísticas en tablas, ejemplos.
SQL>EXEC
dbms_stats.delete_table_stats(ownname => 'USUARIO', tabname =>
'NOMBRE_TABLA');
ii)
Eliminación
de estadísticas en índices, ejemplos.
SQL>EXEC
dbms_stats.delete_index_stats(ownname => 'USUARIO', indname => 'NOMBRE_INDICE');
iii)
Eliminación
de estadísticas de un esquema completo.
SQL>exec
DBMS_STATS.delete_schema_stats('USUARIO');
7.5 ALGO SOBRE LOS LOBS
El LOB en Oracle, es el encargado de gestionar
los tipos de datos no estructurados o estructurados como texto, gráficos, audio
y video y una de sus características principales es el gran tamaño que dichos
campos pueden manejar como largas estructuras de información(puede alcanzar
hasta 4GB). Pero ante lo anterior también el crecimiento sobre la base de datos
es fuerte, por lo tanto es necesaria la revisión para su optimización:
-
Las
siguientes sentencias suministran información de los segmentos LOBS que se
encuentran en la base de datos
La siguiente sentencia extracta información del
Esquema, tabla, columna y nombre del segmento LOB, adicional el Tablespaces que
lo almacena y el nombre del índice. Los segmentos LOBS listados no pertenecen a
Esquemas del sistema.
SQL> SELECT *
FROM DBA_LOBS
where owner NOT in ('SYS','SYSTEM','SCOTT','AURORA$JIS$UTILITY$','AURORA$ORB$UNAUTHENTICATED','OLAPDBA','OLAPSYS','OLAPSVR','ORDPLUGINS','ORDSYS','OSE$HTTP$ADMIN','OUTLN','PUBLIC','QS','QS_ADM','QS_CB','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS','RMAN','SH','WKSYS','CTXSYS','MDSYS','OE','WMSYS','DBSNMP','ANONYMOUS','XDB','TRACESVR','DIP','PERFSTAT','DMSYS','EXFSYS','MDDATA','MGMT_VIEW','ORACLE_OCM','SI_INFORMTN_SCHEMA','SYSMAN','TSMSYS');
-
La
siguiente sentencia extracta información del Esquema, nombre del segmento LOB,
tamaño actual del segmento y Tablespaces en el cual se almacena el LOB. Los
segmentos LOBS listados no pertenecen a Esquemas del sistema
SELECT owner,
segment_name, bytes/1024/1024, tablespace_name
FROM DBA_SEGMENTS
where segment_name
in (
SELECT segment_name
FROM DBA_LOBS
where owner not in
('SYS','SYSTEM','SCOTT','AURORA$JIS$UTILITY$','AURORA$ORB$UNAUTHENTICATED','OLAPDBA','OLAPSYS','OLAPSVR','ORDPLUGINS','ORDSYS','OSE$HTTP$ADMIN','OUTLN','PUBLIC','QS','QS_ADM','QS_CB','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS','RMAN','SH','WKSYS','CTXSYS','MDSYS','OE','WMSYS','DBSNMP','ANONYMOUS','XDB','TRACESVR','DIP','PERFSTAT','DMSYS','EXFSYS','MDDATA','MGMT_VIEW','ORACLE_OCM','SI_INFORMTN_SCHEMA','SYSMAN','TSMSYS'));
-
La
siguiente sentencia suministra el tamaño en Megabytes de los segmentos LOBS que
contiene la base de datos y que no pertenecen a Esquemas del sistema.
SQL> SELECT
sum(BYTES/1024/1024) MEGABYTES
FROM DBA_SEGMENTS
where segment_name
in (
SELECT segment_name
FROM DBA_LOBS
where owner not in
('SYS','SYSTEM','SCOTT','AURORA$JIS$UTILITY$','AURORA$ORB$UNAUTHENTICATED','OLAPDBA','OLAPSYS','OLAPSVR','ORDPLUGINS','ORDSYS','OSE$HTTP$ADMIN','OUTLN','PUBLIC','QS','QS_ADM','QS_CB','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS','RMAN','SH','WKSYS','CTXSYS','MDSYS','OE','WMSYS','DBSNMP','ANONYMOUS','XDB','TRACESVR','DIP','PERFSTAT','DMSYS','EXFSYS','MDDATA','MGMT_VIEW','ORACLE_OCM','SI_INFORMTN_SCHEMA','SYSMAN','TSMSYS'));
-
La
siguiente sentencia permite mover un segmento Lob a otro tablespace. se debe
incluir el nombre de la tabla (<your_table>), la columna Lob
(<lob_column>) y el tablespace hacia el cual será movido el segmento.
SQL> alter table
<your_table> move lob (<lob_column>) store as (tablespace
<tablespace_lob>);
SQL> select
'alter table '||owner||'.'|| table_name || ' move lob ('|| column_name ||')
store as (tablespace PNET_LOBS_32K);'
from dba_lobs
where owner in
('PNET');
7.6 SOBRE LA MEMORIA.
-
Uno de los
objetivos para la optimización de la base de datos, es el de proporcionar
información de las sentencias de mayor consumo en la memoria asignada a la base
de datos propiamente la SGA y PGA, el siguiente query permite gestionar las
sentencias en memoria con mayor consumo y su cantidad de ejecuciones.
SQL>SELECT sql_id,
executions, FIRST_LOAD_TIME,SHARABLE_MEM,DISK_READS,BUFFER_GETS,ROWS_PROCESSED
FROM V$SQL
ORDER BY EXECUTIONS
DESC;
Para
consultar la sentencia especifica:
SELECT * FROM
V$SQLTEXT WHERE SQL_ID='<sql_id>';
SELECT * FROM
V$SQLAREA WHERE SQL_ID='<sql_id>yfhydmk9';
7.6.1 INDICADOR BUFFER HIT RATIO
· Uno de los
seguimientos más recomendados sobre la ejecución de las sentencias SQL en la
base de datos, es la lectura sobre el parámetro HIT RATE, Es un valor
porcentual que va desde 0 hasta 100. Este valor representa una relación de
lecturas de bloques consistentes (Lecturas/Escrituras en la SGA, para ser más
exacto en la Buffer Cache) vs las lecturas físicas (Lecturas/Escrituras de
bloques de datos en disco) que se realizan al ejecutar un SQL. Lo óptimo es que
este valor este entre 85% y 100%, ya que eso nos indicaría que la sentencia
trabaja más sobre los bloques de datos de la Buffer Cache que sobre los bloques
de datos de los datafile almacenados en disco, si el valor retornado es menor a
85 es necesario analizar la sentencia para ver que se puede optimizar.
-
SQL con Hit Rate inferior al 85% y con más de
1000 bloques leídos en disco, ordenados de manera ascendente por el Hit Rate
SQL>SELECT
sql_text, disk_reads, buffer_gets, module,
(buffer_gets -
disk_reads) / buffer_gets hit_rate
FROM v$sqlarea
WHERE buffer_gets
!= 0
AND (buffer_gets -
disk_reads) / buffer_gets < .85
AND disk_reads >
1000
ORDER BY 4;
-
SQL con más de 1000 bloques leídos en disco,
ordenados de manera descendente por el campo Disk_Reads
SQL>SELECT
sql_text, disk_reads, buffer_gets, module,
(buffer_gets -
disk_reads) / buffer_gets hit_rate
FROM v$sqlarea
WHERE buffer_gets
!= 0
AND disk_reads >
1000
ORDER BY 4;
- La
siguiente sentencia permite realizar un seguimiento sobre el indicador BUFFER
HIT RATIO, el cual debería estar con un valor superior al 96%, lo que permite
validar la eficiencia de los bloques Buffer utilizados por la base de datos.
select
1 - ((a.value - (b.value))/d.value)
"Cache Hit Ratio"
from
v$sysstat a,
v$sysstat b,
v$sysstat d
where
a.name='physical reads'
and
b.name='physical reads direct'
and
d.name='session logical reads';
- Para poder
adecuar nuevamente el uso de la memoria se debe realizar el siguiente
procedimiento:
Existe el parámetro DB_CACHE_SIZE, si el
indicador es bajo, se debe incrementar la memoria asignada a este parámetro que
por defecto se encuentra en 64MB, se debe empezar a probar con valores un poco
más altos como 100MB.
- La
siguiente sentencia permite hacer la misma verificación del indicador del
BUFFER HIT RATIO pero de forma individual por cada usuario logeado en la base
de datos.
SQL>SELECT a.username
"Username",
b.consistent_gets "Consistent
Gets",
b.block_gets "DB Block Gets",
b.physical_reads "Physical
Reads",
Round(100* (b.consistent_gets +
b.block_gets - b.physical_reads) /
(b.consistent_gets + b.block_gets),2)
"Hit Ratio %"
FROM v$session a,
v$sess_io b
WHERE a.sid = b.sid
AND (b.consistent_gets + b.block_gets) > 0
AND a.username IS NOT NULL;
7.6.2 ACERCA DEL SHARED POOL
-
La
siguiente sentencia consolida la información de la SGA con el tamaño de memoria
que tiene.
SQL> select
pool, sum(bytes)/1024/1024 from
v$sgastat group by pool;
- La
siguiente sentencia extracta el tamaño de cada componente que se encuentra en
el área de memoria SHARED_POOL.
SQL> SELECT *
FROM v$sgastat
WHERE pool = 'shared pool'
AND (NAME IN
('free memory', 'sql area', 'library
cache', 'miscellaneous',
'row cache', 'KGH: NO ACCESS')
);
- La
siguiente sentencia libera el área de memoria SHARED_POOL (VALIDAR BIEN EL
MOMENTO EN QUE SE VA A EJECUTAR)
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
- Permite
validar el indicador de eficiencia de la shared pool y library cache, Si el
porcentaje es inferior al 99% es un indicador de contención.
SQL> SELECT
name,
(1-(misses/gets))*100
AS "Ratio",
sleeps
FROM v$latch
WHERE name in
('library cache', 'shared pool');
- La
siguiente sentencia permite validar la relación de eficiencia de los RedoLog.
SQL> SELECT
h.pid, n.name, (l.misses/l.gets)*100 wait_ratio
FROM v$latchholder
h, v$latchname n, v$latch l
WHERE h.laddr =
l.addr
AND l.latch# =
n.latch#
AND n.name in
('redo allocation', 'redo copy');
Tenga en cuenta que si la relación un output y el wait_ratio es superior a 1, hay un problema. A
continuación, tendrá que aumentar el tamaño del Redo Log Buffer.
- La
siguiente sentencia suministra los objetos con mayor número de ejecuciones
SQL> SET
PAGESIZE 90
Set linesize 500
column owner format
a13
column name_type
format a10
column name format
a70
select owner, name||' - '||type name, executions
from v$db_object_cache
where
executions > 100
and type in ('PACKAGE', 'PACKAGE BODY',
'FUNCTION', 'PROCEDURE')
order by
executions desc;
· Sentencia
que permite ver como sería el comportamiento de la base de datos de acuerdo a
un valor de memoria asignado
SELECT *
FROM
V$SGA_TARGET_ADVICE
ORDER BY 1;
SELECT *
FROM
V$PGA_TARGET_ADVICE
ORDER BY 1;
7.7 ACERCA DEL RECYCLEBIN
- Existe en
Oracle una especie de papelera de reciclaje sobre los objetos de los esquemas
que han sido eliminados:
Las
siguientes sentencias muestran información de los objetos que se encuentran en
la papelera de reciclaje de la base de datos
SQL> select
count(1) from dba_recyclebin;
- La
siguiente sentencia suministra la información en Megabytes del espacio a
liberar de la papelera de reciclaje.
SQL>SELECT
sum(bytes/1024/1024) LIBERADO
FROM DBA_RECYCLEBIN
R, DBA_SEGMENTS S
where
segment_name=R.object_name;
- La
siguiente sentencia permite liberar los objeto que se encuentran en la papelera
de reciclaje
SQL> purge dba_recyclebin;
- El parámetro
es dinámico en 10g y no necesita reinicio de la base de datos. Para 11g es
necesario reiniciar.
SQL> alter
system set recyclebin=off scope=both;
7.8 SENTENCIAS DE ALTO CONSUMO Y
SESSIONES PEGADAS
7.8.1 identificar usuarios
activos y con ejecuciones en la base de datos
· Existen
diferentes procesos sobre la base de datos que nos generan alto consumo, tanto
de memoria como de espacio, para lo anterior se debe tener en cuenta el
análisis tanto de sistema operativo como del mismo motor de la base de datos.
-
Con la
siguiente sentencia se puede determinar los usuarios conectados actualmente a
la base de datos.
SELECT
V$SESSION.LOGON_TIME CONEXION,
SUBSTR(V$PROCESS.SPID,1,5)
UNIX,
SUBSTR(TO_CHAR(V$SESSION.SID),1,3)
SID,
SUBSTR(V$SESSION.USERNAME,1,10)
USUARIO,
SUBSTR(TO_CHAR(V$SESSION.SERIAL#),1,6)
NSERIE,
SUBSTR(V$SESSION.OSUSER,1,10)
OSUSER,
SUBSTR(V$SESSION.STATUS,1,10)
ESTADO,
SUBSTR(V$SESSION.SERVER,1,7)
SERVER,
SUBSTR(V$SESSION.MACHINE,1,30)
MAQUINA,
SUBSTR(V$SESSION.SECONDS_IN_WAIT,1,10)
SEGUNDOS_EN_ESPERA
FROM
V$SESSION,
V$PROCESS
WHERE
(V$SESSION.PADDR =
V$PROCESS.ADDR) AND
(V$SESSION.USERNAME
IS NOT NULL) AND
(V$SESSION.SERVER
LIKE 'DEDIC%') AND
SUBSTR(V$SESSION.STATUS,1,10)
LIKE 'ACTIV%'
ORDER BY
V$PROCESS.SPID;
7.8.2 BUSCAR LA SESSION POR PID Y
VER LA QUERY SQL
·
En Oracle tenemos
un montón de tablas y vistas que nos permiten obtener muchos datos de
la instancia. Vamos a ver algunos campos de las vistas v$session, v$process y v$sqlarea para
obtener el identificador de sesión y la query para poder matar las query a
partir del PID del sistema operativo.
En
la vista v$session tenemos información de las sesiones, los campos
que para este caso nos interesan son:
-
SID (identificador
de sesión) combinado con el SERIAL# (serial de sesión) nos sirven
para matar la query.
-
PADDR:
Dirección del proceso de la sesión, debemos combinarlo con v$process para
obtener más datos
-
SQL_ID:
Identificador de la sentencia que se ejecuta, debemos combinarlo con v$sqlarea para
obtener más datos.
En
la vista v$process podremos obtener más datos sobre el proceso, entre
ellos el PID del sistema operativo:
-
ADDR:
Dirección del proceso de la sesión, el cual lo tenemos de v$session.
-
PID:
Identificación de proceso de Oracle, se trata de un identificador interno
-
SPID:
Identificación de proceso del sistema operativo
Por
lo tanto, combinando las dos vistas podemos obtener los SID y
SERIAL# para todas las sesiones con su correspondiente PID de sistema
operativo:
SQL> select SID, s.SERIAL#, SPID from v$session s, v$process p
where s.paddr=p.addr;
En el caso que quisiéramos
obtener el SID y el SERIAL# para un PID concreto solo debemos añadir
una condición al WHERE:
SQL> select SID, s.SERIAL#, SPID from v$session s, v$process p
where s.paddr=p.addr and
SPID='28285';
· Para obtener la query que está ejecutando una
sesión deberemos ver la vista v$sqlarea, algunos de sus campos son:
SQL_ID: Identificador de la sentencia que se ejecuta.
SQL_TEXT: Primeros 1000 caracteres de la sentencia.
SQL_FULLTEXT: La sentencia entera.
Por
lo tanto, para ver la sentencia de todas las sesiones ejecutaríamos la
siguiente query:
SQL> select SID, s.SERIAL#, SPID, a.sql_text from v$session s, v$process
p, v$sqlarea a where s.paddr=p.addr and
s.sql_id=a.sql_id;
7.8.3 SESSIONES DE ALTO CONSUMO
DE CPU
·
La
siguiente sentencia nos permite determinar las sesiones que tienen alto consumo
de CPU
SQL> column s.username format a10
column s.serial# format a10
column s.p.spid format a10
column s.module format a10
column a.SQL_ID format a10
SELECT s.sid, s.serial#, p.spid as "OS PID",s.username,
s.module, st.value/100 as "CPU sec", a.SQL_ID
FROM v$sesstat st, v$statname sn, v$session s, v$process p, v$sqlarea a
WHERE sn.name = 'CPU used by this session' -- CPU
AND st.statistic# = sn.statistic#
AND st.sid = s.sid
AND s.paddr = p.addr
AND s.last_call_et < 1800 -- active within last 1/2 hour
AND s.logon_time > (SYSDATE - 240/1440) -- sessions logged on within
4 hours
AND s.sql_id=a.sql_id
ORDER BY st.value;
·
La
siguiente sentencia le permite identificar que script se está ejecutando,
De la
consulta anterior se toma el valor de SQL_ID y se reemplaza en la variable con
ese nombre.
SQL>column SQL_ID format a15
column SQL_TEXT format a100
select SQL_ID, SQL_TEXT from
v$sqlarea where SQL_ID='9g81c49zdvn2b';
7.8.4 MATAR SESSIONES
·
Identificado
el SID y el SERIAL# de la sesión se puede proceder a matar su conexión.
SQL> ALTER
SYSTEM KILL SESSION 'sid,serial#' immediate;
·
Oracle 11g
introduce la sintaxis ALTER SYSTEM DISCONNECT SESSION un Nuevo método de
matar una sesion Oracle. Lo que hace este comando es matar el proceso de
servidor dedicado ( o circuito virtual cuando se utilizan los Shared Sever), lo
que es equivalente a matar el proceso desde el sistema operativo. La sintaxis
básica es similar a la del comando KILL SESSION más la cláusula
POST_TRANSACTION.
SQL> ALTER SYSTEM DISCONNECT SESSION 'sid,serial#' POST_TRANSACTION;
SQL> ALTER SYSTEM DISCONNECT SESSION 'sid,serial#' IMMEDIATE;
·
La
siguiente sentencia suministra la información de las sesiones que está ejecutando
un Esquema específico y la presenta ordenándolas por el campo PGA_MAX_MEM
(Máxima cantidad de memoria asignada al proceso).
SQL> column
username format a12
column status
format a10
column machine
format a10
column sql_id
format a15
column state format
a10
select
s.sid,s.serial#,s.username,status,machine, sql_id, logon_time, state,
pga_used_mem, pga_alloc_mem, pga_freeable_mem,pga_max_mem
from v$session
s,v$process p
where
p.ADDR=s.PADDR
and sChemaname='MFE_USER'
order by
p.PGA_MAX_MEM;
-
La siguiente
sentencia suministra el script completo que se encuentra identificado con el
sql_id suministrado.
SQL>select
s.SQL_FULLTEXT
from v$sql s
where s.SQL_ID
='d4bawfjxjypnq';
7.9 ACERCA DE OBJETOS
7.9.1 mover tablas a otro
tablespace
·
La
siguiente sentencia permite mover una tabla a otro tablespace
SQL>SELECT
'alter table ' || OWNER || '.' || table_NAME || ' move tablespace GIPS;'-- , num_rows
from dba_tables
where owner in
('GIPS')
AND
TABLESPACE_NAME='USERS';
· La
siguiente sentencia permite mover una tabla con un referente Lob a otro
tablespace.
Se debe incluir el nombre de la columna (<COLUMN_NAME>) y el tablespace hacia
el cual será movido el segmento.
SELECT 'ALTER TABLE
' || owner || '.' || table_name || '
MOVE LOB (' || COLUMN_NAME || ') STORE AS (TABLESPACE GIPS); '
FROM DBA_LOBS
WHERE OWNER IN
('GIPS')
AND TABLESPACE_NAME='USERS';
7.9.2 DETALLE DE TABLAS DE UN
USUARIO REGISTROS Y TAMAÑOS
· Con el
objetivo de verificar el tamaño de una tabla específica de un esquema, su
cantidad de registros entre otros datos y con el fin de depurar o afinar la DB
se recomienda ejecutar la siguiente sentencia.
SQL>SELECT
t.table_name,
t.tablespace_name,
t.num_rows,
t.avg_row_len,
t.blocks,
t.empty_blocks,
ROUND(t.blocks * ts.block_size/1024/1024,2)
AS size_mb
FROM dba_tables t
JOIN dba_tablespaces ts ON
t.tablespace_name = ts.tablespace_name
WHERE t.owner = UPPER('UXXIAC')
7.10 BORRADO MASIVO DE OBJETOS
En ocasiones es necesario depurar los objetos inválidos o borrarlos para afinar la base de datos, para hacer este proceso es necesario estar seguro de que dichos objetos no son necesarios. Se recomienda generar un backup de la base de datos para crear un punto de restauración de ser necesario (ver: 9. SOBRE BACKUP Y RESTAURACION DE BASES DE DATOS). Y de igual manera generar los siguientes scripts con el usuario SYS o SYSTEM.
7.10.1 BORRAR TRIGGERS INVALIDOS EN FORMA MASIVA
· La siguiente sentencia dinámica genera los scripts para el borrado masivo de todos los TRIGGERS en estado INVÁLIDO.
SQL>select 'drop trigger "'||owner||'"."'||object_name||'";'FROM DBA_OBJECTS WHERE STATUS='INVALID' AND OBJECT_TYPE ='TRIGGER';
En ocasiones es necesario depurar los objetos inválidos o borrarlos para afinar la base de datos, para hacer este proceso es necesario estar seguro de que dichos objetos no son necesarios. Se recomienda generar un backup de la base de datos para crear un punto de restauración de ser necesario (ver: 9. SOBRE BACKUP Y RESTAURACION DE BASES DE DATOS). Y de igual manera generar los siguientes scripts con el usuario SYS o SYSTEM.
7.10.1 BORRAR TRIGGERS INVALIDOS EN FORMA MASIVA
· La siguiente sentencia dinámica genera los scripts para el borrado masivo de todos los TRIGGERS en estado INVÁLIDO.
SQL>select 'drop trigger "'||owner||'"."'||object_name||'";'FROM DBA_OBJECTS WHERE STATUS='INVALID' AND OBJECT_TYPE ='TRIGGER';
7.10.2 BORRAR VISTAS (VIEW)
INVALIDAS EN FORMA MASIVA
· La siguiente
sentencia dinámica genera los scripts para el borrado masivo de todos las
VISTAS en estado INVÁLIDO.
SQL>select 'drop
VIEW "'||owner||'"."'||object_name||'";'FROM DBA_OBJECTS
WHERE
STATUS='INVALID' AND OBJECT_TYPE ='VIEW';
7.10.3 BORRAR VISTAS materializadas
(MATERIALIZED VIEW) INVALIDaS EN FORMA MASIVA
· La
siguiente sentencia dinámica genera los scripts para el borrado masivo de todos
las VISTAS MATERIALIZADAS en estado INVÁLIDO.
SQL>select 'drop MATERIALIZED VIEW "'||owner||'"."'||object_name||'";'FROM DBA_OBJECTS
WHERE STATUS='INVALID' AND OBJECT_TYPE ='MATERIALIZED VIEW';
7.10.4 BORRAR procedimientos
(procedure) INVALIDOS EN FORMA MASIVA
· La
siguiente sentencia dinámica genera los scripts para el borrado masivo de todos
los PROCEDIMIENTOS en estado INVÁLIDO.
SQL>select 'drop procedure
"'||owner||'"."'||object_name||'";'FROM DBA_OBJECTS WHERE
STATUS='INVALID' AND OBJECT_TYPE ='PROCEDURE';
7.10.5 BORRAR FUNCIONES
(FUNCTION) INVALIDOS EN FORMA MASIVA
·
La
siguiente sentencia dinámica genera los scripts para el borrado masivo de todas
las FUNCIONES en estado INVÁLIDO.
SQL> select 'drop FUNCTION
"'||owner||'"."'||object_name||'";'FROM DBA_OBJECTS
WHERE STATUS='INVALID' AND OBJECT_TYPE ='FUNCTION';
7.10.6 BORRAR PAQUETES (PACKAGE) INVÁLIDOS EN FORMA MASIVA
· La
siguiente sentencia dinámica genera los scripts para el borrado masivo de todas
los PAQUETES en estado INVÁLIDO.
SQL>select 'drop PACKAGE
"'||owner||'"."'||object_name||'";'FROM DBA_OBJECTS
WHERE STATUS='INVALID' AND OBJECT_TYPE ='PACKAGE';
SQL>select 'drop PACKAGE "'||owner||'"."'||object_name||'";'FROM
DBA_OBJECTS
WHERE STATUS='INVALID' AND OBJECT_TYPE ='PACKAGE BODY';
7.10.7 BORRAR TODOS LOS OBJETOS
DE UN ESQUEMA
· En
ocasiones es necesario borrar todos los objetos de un esquema o varios esquemas
de la base de datos pero que no se afecte el usuario que ya se encuentra creado
incluyendo que su contraseña queda igual.
La
siguiente sentencia dinámica genera los scripts para el borrado masivo de todos
los objetos propios del usuario relacionado. (Ejecutar con usuario SYS)
SET ECHO OFF
SET HEADING OFF
SET PAGESIZE 0
SET FEEDBACK OFF
SET TIMING OFF
SET TIME OFF
SET TRIMSPOOL ON
SET TRIMOUT ON
SET LINESIZE 100
SET TERMOUT OFF
SPOOL eliminar-todo
SELECT 'DROP '|| UO.OBJECT_TYPE ||' "'||UO.OWNER||'"."'
|| UO.OBJECT_NAME || '"' ||
DECODE(UO.OBJECT_TYPE,
'CLUSTER', ' INCLUDING
TABLES CASCADE CONSTRAINTS',
'OPERATOR', ' FORCE',
'TABLE', ' CASCADE
CONSTRAINTS',
'TYPE', ' FORCE',
'VIEW', ' CASCADE
CONSTRAINTS',
'') || ';'
FROM All_OBJECTS UO
LEFT JOIN USER_RECYCLEBIN UR ON UO.OBJECT_NAME=UR.OBJECT_NAME
WHERE UO.OBJECT_TYPE IN (
'CLUSTER', 'CONTEXT',
'DATABASE LINK', 'DIMENSION', 'DIRECTORY', 'FUNCTION', 'INDEX TYPE',
'JAVA', 'LIBRARY',
'MATERIALIZED VIEW', 'OPERATOR', 'OUTLINE', 'PACKAGE', 'PROCEDURE',
'SEQUENCE', 'SYNONYM',
'TABLE', 'TYPE', 'VIEW'
)
AND UR.OBJECT_NAME IS NULL
AND OWNER NOT IN('SYS','SYSTEM','SYSMAN','OUTLN','WMSYS','XS$NULL','ORDSYS','ORDDATA','ORDPLUGINS','MDSYS','WKSYS','OLAPSYS','APPQOSSYS','XDB')
ORDER BY UO.OBJECT_TYPE, UO.OBJECT_NAME;
SPOOL OFF
SET TERMOUT ON
· Nota: Una recomendación
sobre los objeto que ya fueron previamente borrados y se encuentran en el
RECYCLEBIN es el de ejecutar el purge.
SQL>PURGE RECYCLEBIN;
7.10.8 REGLAS DE INTEGRIDAD Y LA COLUMNA A LA QUE AFECTAN
· La
siguiente sentencia determina las reglas de la integridad y las respectivas
columnas que afectan y determina el objeto al cual pertenece la columna.
SQL>SELECT constraint_name, table_name, column_name FROM
sys.all_cons_columns;
7.10.9 DESHABILITAR TODAS LAS
FOREIGN KEYS DE TODAS LAS TABLAS PARA BORRADO DE DATA
·
Deshabilitar
BEGIN
FOR c IN
(SELECT c.owner, c.table_name,
c.constraint_name
FROM user_constraints c,
user_tables t
WHERE c.table_name = t.table_name
AND c.status = 'ENABLED'
AND c.CONSTRAINT_TYPE =
'R'
ORDER BY c.constraint_type
DESC)
LOOP
dbms_utility.exec_ddl_statement('alter table ' || c.owner ||
'.' || c.table_name || 'disable
constraint ' || c.constraint_name);
END LOOP;
END;
·
Volver a habilitar
BEGIN
FOR c IN
(SELECT c.owner, c.table_name,
c.constraint_name
FROM user_constraints c,
user_tables t
WHERE c.table_name =
t.table_name
AND c.status = 'DISABLED'
AND c.CONSTRAINT_TYPE =
'R'
ORDER BY c.constraint_type)
LOOP
dbms_utility.exec_ddl_statement('alter table ' || c.owner ||
'.' || c.table_name || ' enable
constraint ' || c.constraint_name);
END LOOP;
END;
7.10.10 Borrar estadísticas
históricas en tablespace SYSAUX
· Siempre que
las estadísticas en el diccionario se modifican, las versiones antiguas se
guardan automáticamente para una futura restauración. Las estadísticas
históricas se purgan automáticamente a intervalos regulares en función del
valor de retención. La retención es configurable mediante el procedimiento
ALTER_STATS_HISTORY_RETENTION, el valor por defecto de esta configuración
corresponde a 31 días, que normalmente no es demasiado grande, pero puede ser
un problema en bases de datos pequeñas, ya que el tablespace SYSAUX puede
crecer en un tamaño no soportado o bien consumir recursos que se tienen
designados a otros tablespaces.
· A continuación se
detalla el procedimiento para corregir el crecimiento excesivo de las tablas
asociadas a la retención de estadísticas.
-
Verificar
espacio utilizado por estadísticas históricas.
set linesize 120
set pagesize 100
COLUMN
"Item" FORMAT A25
COLUMN "Space
Used (GB)" FORMAT 999.99
COLUMN
"Schema" FORMAT A25
COLUMN "Move
Procedure" FORMAT A40
SELECT
occupant_name "Item",
space_usage_kbytes/1048576
"Space Used (GB)",
schema_name "Schema",
move_procedure "Move Procedure"
FROM v$sysaux_occupants
ORDER BY 1
/
NOTA: La vista dinámica V$SYSAUX_OCCUPANTS
indica, entre otras cosas, las aplicaciones que usan SYSAUX, el espacio
utilizado, el nombre del esquema propietario de la mismas y el nombre del
procedimiento que debe emplearse para desplazar determinado contenido desde
SYSAUX hasta otra localización.
- ¿Cuánto
tiempo se mantienen las estadísticas históricas?
SQL>select dbms_stats.get_stats_history_retention
from dual;
Por
defecto son 31 Dias
-
Establecer la
retención de las estadísticas históricas 10 días.
SQL>exec
dbms_stats.alter_stats_history_retention(10);
- Borrar las
estadísticas históricas de más de 10 días.
Nota:
(la mejor manera de hacerlo por etapas si existe una gran cantidad de datos
(SYSDATE-30, sydate-25, etc)
exec DBMS_STATS.PURGE_STATS(SYSDATE-10);
- Mostrar las
estadísticas disponibles que no han sido borradas.
- Muestra el
tamaño de las tablas a reconstruir después del borrado de
las estadísticas históricas.
col Mb form 9,999,999
col SEGMENT_NAME form a40
col SEGMENT_TYPE form a6
set lines 120
select sum(bytes/1024/1024) Mb, segment_name,segment_type from
dba_segments
where tablespace_name = 'SYSAUX'
and segment_name like 'WRI$_OPTSTAT%'
and segment_type='TABLE'
- Muestra el tamaño de los indices
a reconstruir después del borrado de las estadísticas históricas.
col Mb form 9,999,999
col SEGMENT_NAME form a40
col SEGMENT_TYPE form a6
set lines 120
select sum(bytes/1024/1024) Mb, segment_name,segment_type from
dba_segments
where tablespace_name = 'SYSAUX'
and segment_name like '%OPT%'
and segment_type='INDEX'
group by segment_name,segment_type order by 1 asc
/
7.10.11 Borrar los sinónimos públicos
· Para poder borrar los sinónimos públicos que
estén asociados a objetos o tablas de un esquema es necesario determinar el
nombre del sinónimo, de igual manera es necesario invalidar algunos triggers
que se disparan en el proceso del borrado.
SYS.AW_DROP_TRG
SYS.XDB_PI_TRIG
· La siguiente sentencia dinámica permite crear
los scripts para el borrado de todos los sinónimos públicos. (Se recomienda
crear un spool y ejecutarlos desde una consola de sqlplus con el usuario sys).
SQL>select 'drop public synonym "'||object_name||'";' from
all_objects where object_type='SYNONYM' and OWNER='PUBLIC';
7.11 BLOQUEO EN LA BASE DE DATOS
·
Una de las
principales gestiones sobre la base de datos en el momento de presentarse
lentitud en las ejecuciones es la de verificar que no existan procesos
bloqueados, lo anterior significa que sentencias sql que afectan los mismos
objetos al mismo tiempo generan bloqueos entre si.
Para
lo anterior se solicita efectuar la siguiente revisión.
-
Ejecutar la
siguiente sentencia para validar los bloqueos entre usuarios.
SQL>select
s1.username || '@' || s1.machine
|| ' ( SID=' || s1.sid || ' ) is blocking '
|| s2.username || '@' || s2.machine || ' (
SID=' || s2.sid || ' ) ' AS blocking_status
from v$lock l1, v$session s1, v$lock l2,
v$session s2
where s1.sid=l1.sid and s2.sid=l2.sid
and l1.BLOCK=1 and l2.request > 0
and l1.id1 = l2.id1
and l2.id2 = l2.id2 ;
De
encontrar un bloqueo, determinar cuál es el SID del usuario que está bloqueando
los demás y proceder a matar la sesión para liberar los demás.
7.12 TEST DE DIAGNOSTICO DE SU BASE DE DATOS
· Una de las
recomendaciones que de forma personal hago para los administradores de Oracle,
es el de hacer un diagnóstico de cómo es el estado de la base de datos al
momento de recibirla, este proceso le proporcionara una idea de cómo se
encuentra la DB y cuáles serían las posibles mejoras a aplicar.
Anexo
el siguiente cuadro como check-list que he elaborado para de forma secuencial
detallar el estado de la DB con sus respectivos apuntes.
#
|
Detalle
|
SQL
|
Observaciones y soluciones
|
1
|
Tenga en claro las características del motor
de la base de datos, su versión y la plataforma sobre la cual está montada.
|
Sql>select * from v$version;
Sql>select * from product_component_version;
|
Se detalla la información a nivel de versión del motor de Oracle
y sobre que se encuentra instalado.
|
2
|
Consultar el nombre de la base de datos a
revisar.
|
select value from v$system_parameter where name = 'db_name'
|
Determinar el nombre exacto de la base de datos a trabajar.
|
3
|
Consultar los parámetros de la Base de datos.
|
Sql>select * from v$parameter;
Sql>select * from v$system_parameter order by 2;
|
Se debe tener claro los valores de cada uno de los parámetros y
de cuales se deben variar según los requerimientos o tamaño de la base de
datos.
|
4
|
Consultar la ubicación de los archivos de
DATA_FILES
|
Sql>select * from DBA_DATA_FILES;
|
El objetivo es poder definir la ruta de almacenamiento de los
Datafiles para determinar su capacidad de almacenamiento físico y su espacio
libre.
|
5
|
Consultar la ubicación de los archivos de
control de la base de datos.
|
Sql>select value from v$system_parameter where name =
'control_files'
|
El objetivo es poder definir la ruta de almacenamiento de los
Controlfiles para determinar su capacidad de almacenamiento físico y su
espacio libre.
|
6
|
Consultar el tamaño de la base de datos.
|
SQL>SELECT SUM(BYTES)/1024/1024 MB FROM DBA_EXTENTS;
|
Poseer el dato del
tamaño de la base de datos, sirve para calcular tiempos de ejecución según su
tamaño, al igual que definir el tamaño de los espacios asignados a los
backups de la base de datos.
|
7
|
Consultar los usuarios creados en la base de
datos y su estado.
|
Sql>select username, account_status, created, profile from
dba_users;
|
Define el número de
usuarios creados en la base de datos y principalmente su status, lo cual
permite determinar la depuración de los mismos.
|
8
|
Consultar de los anteriores usuarios
existentes en la base de datos, cuáles de ellos son esquemas propietarios de
objetos sin incluir el usuario SYS y SYSTEM.
|
SQL>select DISTINCT(owner)from all_objects where owner not
in('SYS','SYSTEM');
|
Nos permite definir
cuáles usuarios son propietarios de objetos, con el fin de analizar su
respaldo y depuración.
|
9
|
Determine el valor asociado a la memoria de
la base de datos
|
SQL>select sum(value) /1024/1024 from v$sga;
|
Compare el valor de
la memoria asignada a la SGA con respecto a la memoria total del servidor de
base de datos.
|
10
|
Determine el tamaño de los tablespace y la
ubicación de los archivos que los componen
|
SELECT nvl(name,'=== TOTAL for DB ===')
"Tablespace",TO_CHAR(SUM(mbytes),'999,999,999.99') "Total
MB",TO_CHAR(SUM(used),'999,999,999.99') "Used
MB",TO_CHAR(SUM(free),'999,999,999.99') "Free
MB",ROUND(AVG(pct_used),2) "%Used",ROUND(AVG(pct_free),2)
"%Free",'SQLDEV:GAUGE:0:100:0:0:'||AVG(pct_used) AS
"Tablespace Utilization",TO_CHAR(SUM(new_sz),'999,999,999.99')
"Expected Size",TO_CHAR(SUM(add_sz),'999,999,999.99') "Add MB
for desired %" FROM(SELECT name, ROUND(mbytes,2) mbytes, ROUND(used,2)
used, ROUND(free,2) free, ROUND(pct_used,2) pct_used, ROUND(pct_free,2)
pct_free, ROUND(CASE WHEN ( ((100 *used)/ trim(:desired_pct))-mbytes <
0)THEN mbytes ELSE ((100*used)/ trim(:desired_pct)) END,2) new_sz, ROUND(CASE
WHEN ( (((100 *used)/ trim(:desired_pct))-mbytes) < 0 )THEN 0 ELSE (((100
*used)/ trim(:desired_pct))-mbytes) END,2) add_sz FROM (SELECT
NVL(b.tablespace_name, NVL(a.tablespace_name,'UNKOWN')) name, mbytes_alloc Mbytes,
mbytes_alloc-NVL(mbytes_free,0) used, NVL(mbytes_free,0)
free,((mbytes_alloc-NVL(mbytes_free,0))/ mbytes_alloc)*100
pct_used,100-(((mbytes_alloc-NVL(mbytes_free,0))/ mbytes_alloc)*100) pct_free
FROM(SELECT SUM(bytes)/1024/1024 Mbytes_free,MAX(bytes)/1024/1024
largest,tablespace_name FROM dba_free_space GROUP BY tablespace_name)
a,(SELECT SUM(bytes)/1024/1024 Mbytes_alloc, SUM(maxbytes)/1024/1024
Mbytes_max,tablespace_name FROM sys.dba_data_files GROUP BY tablespace_name
UNION ALL
SELECT SUM(bytes)/1024/1024 Mbytes_alloc,
SUM(maxbytes)/1024/1024 Mbytes_max, tablespace_name FROM dba_temp_files GROUP
BY tablespace_name) b WHERE a.tablespace_name (+) = b.tablespace_name))
GROUP BY rollup (name)ORDER BY CASE WHEN
name IS NULL THEN 200 ELSE ROUND(AVG(PCT_FREE),2) END ASC;
|
Esta consulta nos
permite determinar la ubicación de los archivos asociados a los tablespace,
su tamaño, su consumo y posible depuración.
|
11
|
Usuarios con tablespace SYSTEM como temporary
tablespace (exceptuando users SYS y SYSTEM)
|
SQL>select username,default_tablespace from dba_users where
default_tablespace = 'SYSTEM' and username
not in ('SYS','SYSTEM')
|
Reubicar los usuarios
según el informe y según los parámetros de configuración.
|
12
|
Usuarios con tablespace SYSTEM como default
tablespace (exceptuando users SYS y SYSTEM)
|
SQL>select username,temporary_tablespace
from dba_users where temporary_tablespace = 'SYSTEM' and username not in
('SYS','SYSTEM');
|
Reubicar los usuarios
según el informe y según los parámetros de configuración.
|
13
|
Índices UNUSABLES
|
SQL>select owner,count(1) from dba_indexes where status = 'INVALID'
group by owner
SQL> select owner,
index_name, index_type, table_owner,
table_name, table_type, tablespace_name
from dba_indexes
where status = 'INVALID'
|
Identifique según el
listado generado y reconstruya los índices necesarios.
|
14
|
Objetos inválidos
|
SQL>select owner,object_type,count(1) from dba_objects where status
= 'INVALID' group by owner,object_type order by 1,2
SQL> select owner, object_name, created, last_ddl_time from dba_objects where
status = 'INVALID' order by 1,2
|
Valide los objetos
inválidos y compile nuevamente o elimine los que no son usados según análisis
y autorización del propietario de los objetos. (ver 7.3 OBJETOS INVALIDOS)
|
15
|
Paquetes con bodies sin que no tengan sus correspondientes
headers
|
SQL>select unique owner,name from dba_source a where type =
'PACKAGE BODY' and not exists (select null from dba_source b where a.owner
= b.owner and a.name = b.name and b.type = 'PACKAGE')
|
Identificar el bodie
y validar su contenido y asociar su headers o recompilar, en caso contrario
eliminar dicho package.
|
16
|
Constraints deshabilitadas
|
SQL>select owner, case constraint_type when 'P' then 'PRIMARY_KEY' when 'R' then 'FOREIGN_KEY' when 'U' then 'UNIQUE' when 'C'
then 'CHECK' end constraint_type, count(1) from dba_constraints where status
= 'DISABLED' group by owner,constraint_type order by 1,2
|
Identificar y validar
los constraints deshabilitados y depurar según la necesidad.(habilitar o
eliminar)
|
17
|
Identificar bloqueos en la base de datos.
|
SQL>select s1.username || '@' || s1.machine || ' ( SID=' || s1.sid || ' ) is blocking ' || s2.username || '@' || s2.machine || ' (
SID=' || s2.sid || ' ) ' AS blocking_status from v$lock l1, v$session s1, v$lock l2,
v$session s2 where s1.sid=l1.sid and
s2.sid=l2.sid and l1.BLOCK=1 and l2.request > 0 and 1.id1 = l2.id1 and
l2.id2 = l2.id2 ;
|
Identificar proceso o
SID del usuario que está bloqueando las demás sesiones. Matar la sesión para
liberar las demás.
|
18
|
Controlar que la tabla de auditoria sys.aud$
no esté en el tablespace SYSTEM
|
SQL>select name, value, display_value, description from v$parameter where name
like 'audit%'
SQL>select owner, segment_name,
tablespace_name from dba_segments
where segment_name = 'AUD$'
|
Identificar una de
las tablas de mayor consume no este sobre el tablespace propio del sistema,
se recomienda crear un tablespace solo para la auditoria.
|
19
|
Jobs en estado broken
|
SQL>select * from dba_jobs where sysdate > next_date
|
Identificar las
tareas (jobs) existentes en la base de datos que no están funcionales para
activarlos o en caso contrario depurar.
|
20
|
Jobs con fallas
|
SQL>select * from dba_jobs where failures > 0
|
Identificar y depurar
según necesidad.
|
21
|
Roles no otorgados a ningún rol o user
|
SQL>select role from dba_roles
minus
select granted_role from dba_role_privs
|
Identificar y depurar
según necesidad.
|
22
|
Sinónimos públicos que apuntan a objetos
inexistentes
|
SQL>select * from dba_synonyms a
where owner = 'PUBLIC'
and not exists (select null
from
dba_objects b
where
a.table_owner = b.owner
and
a.table_name = b.object_name)
|
Identificar y depurar
según necesidad.
|
23
|
Sinónimos privados que apuntan a objetos
inexistentes
|
SQL>select * from dba_synonyms a
where owner != 'PUBLIC'
and not exists (select null
from
dba_objects b
where
a.table_owner = b.owner
and a.table_name = b.object_name)
|
Identificar y depurar
según necesidad.
|
24
|
Database links que son inaccesibles
|
begin
for i in (select decode(owner,'PUBLIC',user,owner)
owner,db_link from dba_db_links)
loop
begin
execute immediate
'create view 'i.owner'.TEST as select count(1) c from dual@'i.db_link;
dbms_output.put_line('OWNER: 'i.owner'; DB_LINK: 'i.db_link' -->
ACCESIBLE');
execute immediate
'drop view 'i.owner'.TEST';
exception when others then dbms_output.put_line('OWNER:
'i.owner'; DB_LINK: 'i.db_link' --> NO ACCESIBLE');
end;
end loop;
end;
/
|
Identificar y depurar
según necesidad, quitar la asociación a los dblinks falsos ya que puede
presentar objetos inválidos.
|
25
|
Segmentos con más de 100 extents (excluir sys
y system)
|
select * from dba_segments where extents > 100 and owner not in
('SYS','SYSTEM')
|
Identificar y depurar
según necesidad.
Analizar para posible
particionamiento o redistribución.
|
26
|
Tablas no analizadas con más de 1000
registros
|
SQL>set serverout on size 500000
DECLARE l_cnt int;
BEGIN
FOR i IN (SELECT * FROM dba_tables
WHERE last_analyzed IS NULL
AND owner NOT IN ('SYS','SYSTEM'))
LOOP
EXECUTE IMMEDIATE ' select count(1) from
'||i.owner||'.'||i.table_name
INTO l_cnt;
IF (l_cnt > 1000) THEN
DBMS_OUTPUT.put_line(i.owner||'.'||i.table_name);
END IF;
END LOOP;
END;
|
Identificar y depurar
según necesidad.
|
27
|
Tablas con más de 5 índices
|
SQL>select owner,table_name,count(1) as no_indx from dba_indexes where
owner not in ('SYS','SYSTEM') group by owner,table_name having count(1) >
5;
|
Identificar y
analizar el paso a seguir respecto a la cantidad de indices asociados a una
table. Tenga en cuenta que no existe limite pero por cada índice que tenga un
tabla, Oracle deberá actualizarlo cada vez que hagas una transacción, update,
insert, incluso para consultas de datos revisara los índices existentes a ver
si puede utilizar alguno para mejorar el tiempo de respuesta, esto quiere
decir a mas índices más lentitud.
|
28
|
Tablas que no posean primary key y que no
estén vacías
|
SQL>select owner,table_name from
dba_tables a where owner not in ('SYS','SYSTEM') and num_rows > 0 and not exists (select
null from dba_constraints b
where a.owner = b.owner and a.table_name = b.table_name and b.constraint_type =
'P') order by 1,2
|
Según el modelo E-R, toda entidad debe tener una clave
primaria. Esto no es opcional, porque necesariamente necesitas algo que te
permita no sólo identificar un único registro dentro de una tabla que puede
tener millones, sino que también necesitas un modo de asegurarte que el registro
se refiera a una instancia que no esté repetida. Y para eso es la PK.
|
29
|
Indices no analizados
|
select owner,index_name,table_name from
dba_indexes where owner not in ('SYS','SYSTEM')and last_analyzed is null
|
Identificar y depurar
según necesidad.
Analizar para posible
particionamiento o redistribución.
|
30
|
Tablas con más de 100 columnas
|
SQL>select owner,table_name,count(1) from dba_tab_columns where
owner not in ('SYS','SYSTEM') group by owner,table_name
having count(1) > 100
|
Identificar las
tablas que por su tamaño en campos nos pueden presentar lentitud.
|
31
|
Owners que comparten tablespaces
|
select a.owner,b.owner, a.tablespace_name,
a.cantseg, b.cantseg from (select
owner,tablespace_name,count(1) cantseg from dba_segments where owner not in
('SYS','SYSTEM','SYSMAN','OUTLN','DBSNMP','SYSAUX') group by
owner,tablespace_name) a, (select
owner,tablespace_name,count(1) cantseg from dba_segments where owner not in
('SYS','SYSTEM','SYSMAN','OUTLN','DBSNMP','SYSAUX') group by
owner,tablespace_name) b where a.tablespace_name = b.tablespace_name and a.owner != b.owner order by
a.cantseg+b.cantseg desc
|
Analizar y de ser
necesario depurar según standares de aplicación o funcional.
|
32
|
Tablas Candidatas para Particionar
|
select unique a.object_owner,a.object_name from dba_hist_sql_plan a, dba_tab_statistics
b where a.object_owner = b.owner and a.object_name = b.table_name and
a.options = 'FULL' and b.num_rows > 10000000
|
Analizar y depurar.
|
7.13
TRUCOS SQL
7.13.1 Count(*)
Cuando haces una consulta con un count(*) solo para ver cuantos registros tiene una consulta, no deberías utilizar el * ya que la base de datos va y busca las columnas definidas de la tabla(y esto por pequeño que sea toma tiempo) en estos casos puedes hacer algo así:
select count(1) from usuario ;
//el 1 representa el primer campo de la tabla
ó
select count(campo) from usuario ;
En conclusión el tiempo que se toma en ejecutar el segundo query es menor al que se toma si el query tiene el count(*).
7.13.2 Truncate o Delete:
· Cuando vas
a borrar todos los registro de una tabla en la base de datos generalmente
hacemos
SQL>delete from usuario;
Cuando hacemos un delete la base de datos, borra uno a uno los registros de la tabla, los almacena por así decirlo en cache por si de pronto vamos a hacer rollback, esto ocupa más tiempo y espacio en la db sin mencionar que la mantiene bloqueada durante el proceso.(bloqueada quiere decir que si otros usuario la están consultando la transacción queda en cola y no es atendida hasta que la transacción que está haciendo el borrado la libera).
El truco es utilizar truncate porque es más rápido básicamente consiste en mover el índice del registro en el cual estaba el último registro de la bd al primer registro y no borramos uno a uno, sino que como el registro queda en el inicio entonces es como si no hubiera nada.
Como utilizarlo, sencillo:
SQL>truncate usuario;//donde usuario es la tabla
En conclusión, si estás seguro de que vas a borrar todos los datos y no te vas a arrepentir es mejor truncate.
hacemos
SQL>delete from usuario;
Cuando hacemos un delete la base de datos, borra uno a uno los registros de la tabla, los almacena por así decirlo en cache por si de pronto vamos a hacer rollback, esto ocupa más tiempo y espacio en la db sin mencionar que la mantiene bloqueada durante el proceso.(bloqueada quiere decir que si otros usuario la están consultando la transacción queda en cola y no es atendida hasta que la transacción que está haciendo el borrado la libera).
El truco es utilizar truncate porque es más rápido básicamente consiste en mover el índice del registro en el cual estaba el último registro de la bd al primer registro y no borramos uno a uno, sino que como el registro queda en el inicio entonces es como si no hubiera nada.
Como utilizarlo, sencillo:
SQL>truncate usuario;//donde usuario es la tabla
En conclusión, si estás seguro de que vas a borrar todos los datos y no te vas a arrepentir es mejor truncate.
7.13.3 Drop – purge
· Cuando
borramos una tabla de la base de datos oracle, dependiendo de la forma en la
que borremos la tabla va a ser eliminada completamente o solo aparentemente
borrada, veamos el siguiente código.
SQL>drop table usuario;
La
tabla se borra pero realmente queda almacena como una papelera, la prueba está
en que el tamaño del tablespace no disminuye. La alternativa para que realmente
quede eliminada la tabla y no nos ocupe espacio es agregar al final la palabra
purge y quedaría así.
SQL>DROP TABLE USUARIO PURGE;
7.13.4 indices
Indexar
nuestras columnas es una de las maneras más comunes y sencillas de optimizar
nuestras consultas. Sin embargo, se debe tener un profundo conocimiento sobre
cómo funciona el indexado en cada DMBS para utilizar correctamente sus índices.
Dicho de otro modo: crear índices sin sentido, sencillos o absurdos sin
comprender exactamente cómo funciona nuestra Base de Datos puede tener
justamente el efecto contrario al deseado en nuestras consultas, y hacer que
funcionen aún más lentas.
7.13.5 SÍMBOLOS OPERACIONALES
Los
símbolos operacionales como >,<,=,!=, etc. son muy útiles en nuestras
consultas. Se pueden optimizar algunas consultas si la columna con el símbolo
operacional en cuestión esta indexada. Por ejemplo:
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA > 16;
Esta
consulta no está optimizada, ya que el motor de la Base de Datos debe buscar el
valor 16, y DESPUÉS escanear hacia delante del 16 y por detrás.
SQL>SELECT * FROM MI_TABLA
WHERE COLUMNA >= 17;
De este modo, el DMBS debe saltar directamente a los valores mayores a 16. Es casi la misma manera, pero evitas que el DMBS tenga que comparar también los valores menores para ver si entran en la query.
7.13.6 COMODINES
En
SQL, el comodín se nos presenta con el símbolo ‘%’. Usar comodines ralentiza
bastante nuestras consultas, especialmente si la tabla en la que buscamos en
bastante grande. Se pueden optimizar dichas consultas si podemos permitirnos
poner el comodín únicamente como comodín-sufijo, en vez de como comodín-prefijo
o como comodín-total.
#Comodín-total:
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA LIKE '%manzana%';
#Comodín-sufijo:
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA LIKE 'manzana%';
#Comodín-prefijo:
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA LIKE '%manzana';
7.13.7 OPERADOR NOT
Intenta
evitar todo lo posible el operador NOT en SQL. Es mucho más rápido buscar por
un valor exacto (operador positivo) como por ejemplo un LIKE, IN, EXISTS o el
símbolo operacional =, en vez de usar un operador negativo como NOT LIKE, NOT
IN, NOT EXIST o el símbolo != . Usar un operador negativo provoca que la
búsqueda tenga que recorrer cada línea por separado identificar los que no son
o que existen dentro de la tabla. Sin embargo, usando un operador positivo, la
búsqueda para en cuanto se encuentra el resultado.
7.13.8 COUNT Vs EXIST
Muchos
de nosotros solemos usar el operador COUNT para determinar si existe un dato en
particular.
SQL>SELECT COLUMNA FROM MI_TABLA WHERE COUNT(COLUMNA) > 0
;
Este
sistema es muy malo, ya que el COUNT debe contar cada registro de la tabla para
ver cuantos hay. La mejor alternativa es usar el operador EXISTS, que para en
cuanto encuentra el primer registro que concuerda con la búsqueda, sin tener
que contarlos todos. Por lo tanto, existe.
7.13.9 COMODIN Vs SUBSTR
Si
una columna en particular está indexada, es mejor usar un comodín para buscar
en ella en vez de un Substr. El comodín usará el índice, el Substr no.
MAL:
SQL>SELECT * FROM MI_TABLA WHERE Substr(COLUMNA,
1, 1) = 'pepito';
Esta consulta hará Substr a cada registro de la tabla individualmente para rastrear el valor ‘pepito’. Pero del siguiente modo:
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA = 'pepito%' ;
La consulta con comodín corre mucho más rápido en el DBMS. Ejemplo:
#BUSCAR TODAS LAS FILAS QUE EL PRIMER CARACTER ES 'E'
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA = 'E%' ;
7.13.10 FUNCIONES MAX Y MIN
Las
funciones Max y Min buscan el valor Máximo y Mínimo de una
columna. Corrección: Podemos usar Max y Min en columnas que ya están
indexadas. Pero si dicha columna se usa frecuentemente, tener un índice además
debería ayudar a acelerar dichos operadores Max y Min. Decidir si poner un
índice sólo para acelerar los Max y Min no es aconsejable. Los índices son
caros de mantener, y crear índices sólo para acelerar Max y Min es una locura.
Es como sacrificar el bosque entero por un único árbol.
7.13.11 TIPOS DE DATOS
Se
deben usar los tipos de datos más eficientes (más pequeños) siempre que sea
posible. Es innecesario, y algunas veces hasta peligroso, proporcionar tipos de
datos enormes cuando se pueden solucionar un problema con tipos más pequeños.
Por ejemplo, usando los tipos de datos enteros más pequeños para así tener
tablas más pequeñas. MEDIUMINT es a veces una elección mejor que un INT, porque
una columna MEDIUMINT uses 25% menos de espacio en disco. Por otro lado,
VARCHAR es mejor que LONGTEXT para almacenar texto como un email, unas
observaciones o pequeños detalles.
7.13.12 INDICES PRIMARIOS
La
primera columna que se use para un indexado debe ser lo más corta posible. Esto
hace que la identificación de cada fila sea más sencilla y eficiente por parte del
DBMS.
7.13.13 INDEXADO DE CADENAS
No
es necesario indexar toda la cadena cuando en su lugar se pueden indexar un
prefijo o sufijo de la cadena. Es aconsejable llevar a cabo dicha indexación
especialmente si el prefijo o sufijo de la cadena proporciona un identificador
único para la cadena.
Los índices más cortos son más rápidos, no sólo debido a que requieren menos espacio en disco, sino porque también evitan que se acceda a ellos menos veces y a la caché de índice, y por lo tanto menos búsquedas en disco.
Los índices más cortos son más rápidos, no sólo debido a que requieren menos espacio en disco, sino porque también evitan que se acceda a ellos menos veces y a la caché de índice, y por lo tanto menos búsquedas en disco.
7.13.14 LIMITAR EL RESULTADO
Otro
método muy común para optimizar tu query es minimizar el número de filas
devueltas. Si en una tabla tienes varios billones de registros y lanzas una
simple pero potente query sin limitación, puedes echar abajo la Base de Datos
entera.
SQL>SELECT * FROM MI_TABLA;
Si
sólo necesitas una cantidad de registros, trata de limitar el resultado. De
esta forma no sólo serás más eficaz, sino que ayudarás a minimizar el daño que
puede ocasionar un ataque por SQL de este tipo.
SQL>SELECT * FROM MI_TABLA WHERE 1 LIMIT 10 (Sólo
en MySQL) ;
7.13.15 USAR EL VALOR POR DEFECTO
Debemos
aprovechar la ventaja que tienen esta Bases de Datos por el hecho de tener
columnas con valores por defecto. Inserta valor explícitamente únicamente
cuando sean diferentes de los valores por defecto. Esto reduce el análisis
(parsing) que Oracle debe hacer y mejora la velocidad de los INSERTS.
7.13.16 SUBQUERY EN UN IN
Muchos
de nosotros usamos una sub-consulta (o subquery) dentro de un operador IN, tal
que así:
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA IN ( SELECT COLUMNA2 FROM MI_TABLA2 );
Hacer esto es muy caro para el DBMS porque la consulta SQL debe evaluar la query exterior antes que la interior. En vez de esto, podemos usar lo siguiente:
SQL>SELECT * FROM MI_TABLA,
(SELECT COLUMNA2 FROM MI_TABLA2) as dummytableWHERE dummytable.COLUMNA2
= MI_TABLA.COLUMNA;
Usando
una dummytable (o tabla tonta) es mejor que usar un operador IN para hacer una
sub-consulta. Como alternativa, un operador EXIST también es mejor.
7.13.17 UNION EN VEZ DE OR
Los
índices pierden su velocidad cuando se usan en situaciones de OR
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA_1 = 'pepito' OR COLUMNA_2 = 'manolito';
Si hacemos la query anterior usando 2 consultas con UNION, estas sí usarán sus índices.
SQL>SELECT * FROM MI_TABLA WHERE COLUMNA_1 = 'pepito'
UNION
SELECT * FROM MI_TABLA WHERE COLUMNA_2 = 'manolito'
7.13.18 UNION Vs UNION ALL
Pongamos
un ejemplo de una query de SQL en que queremos traer las filas
de TABLA1 y TABLA2. Usamos UNION para unir las dos consultas.
Hasta aquí todo correcto. Pero se puede optimizar si sabemos lo que vamos a
obtener.
SQL>SELECT NOMBRE, APELL FROM TABLA_EMPLEADOS
UNION
SELECT NOM, APE FROM
TABLA_CLIENTES;
Cuando se manda la sentencia al motor de la Base de Datos, realmente lo que hace es consultar TABLA1 con sus registros, consulta TABLA2 con sus registros, los junta, los ordena y les aplica un DISTINCT. Estas dos últimas tareas son las que ejercen más trabajo sobre el motor de Base de Datos, y las que más recursos gastan.
Si sabemos que los registros que vamos a obtener de TABLA1 y TABLA2 son completamente distintos, podemos usar UNION ALL, lo que evita que haga la ordenación y el DISTINCT en el motor de Base de Datos.
SQL>SELECT
NOMBRE, APELL FROM TABLA_EMPLEADOS
UNION ALL
SELECT NOM, APE FROM
TABLA_CLIENTES;
Al
hacer el UNION ALL, realmente lo que se pide es "traeme todos los
registros, aunque esten duplicados". Pero si sabemos que no van a
devolverse registros duplicados, usando esta variante obtendremos el mismo
resultado, pero de forma más eficiente.
7.13.19 BUSCAR EL CARÁCTER % EN
UN LIKE DE UNA SELECT
Necesitábamos
buscar en una tabla de la Base de Datos los textos que contuvieran el símbolo
de tanto por ciento (%).
La
siguiente consulta no generaría lo deseado.
SQL>SELECT * FROM MI_TABLA
WHERE DESCRIPCION LIKE '%%%';
Usando
la cláusula de ESCAPE puedes buscar caracteres que normalmente no los
podrías buscar. Se pueden buscar cadenas de caracteres que incluyan uno o más
caracteres comodín especiales. Para buscar el signo de porcentaje como un
carácter, en lugar de buscarlo como un carácter comodín, hay que proporcionar
la palabra clave ESCAPE y el carácter que
queremos "ignorar". Si no pusiéramos ese símbolo de exclamación
y el ESCAPE '!', devolvería cualquier fila.
SQL>SELECT * FROM MI_TABLA
WHERE DESCRIPCION LIKE '%!%%' ESCAPE '!';
WHERE DESCRIPCION LIKE '%!%%' ESCAPE '!';
7.13.20 MUCHOS JOINS
Ojo
con las consultas con muchas Joins, evitar cruzar muchas tablas. Por el mismo
motivo se deben utilizar las vistas con mucho cuidado, puesto que provocan que
se crucen muchas tablas inadvertidamente
7.13.21 CLONAR UNA TABLA
La
siguiente sentencia nos permite hacer una copia de una tabla específica.
SQL> CREATE TABLE <nueva_tabla> AS SELECT * FROM <table_origen>;
SQL> CREATE TABLE <nueva_tabla> AS SELECT * FROM <table_origen>;
Hay
que tener en cuenta que con esta opción no recupera índices, estadísticas de
tabla, ni nada por el estilo.
7.14 TRUNCATE vs DELETE
Adjunto
un listado de las principales diferencias entre “truncar” y “deletear” todas
las filas de una tabla.
- TRUNCATE es
una operación DDL y es rápido y DELETE una operación DML y es lento.
- TRUNCATE
resetea el HWM y libera el espacio, DELETE no.
- TRUNCATE no
tiene vuelta atrás, ni siquiera se puede hacer un flashback. Es raro que se
pueda hacer flashback de un drop pero no de un truncate, no?. Con delete se
puede hacer un rollback y si ya se confirmó el borrado (commit) se podría
utilizar flashback.
- TRUNCATE no
dispara DML's triggers asociados a la tabla truncada.
- TRUNCATE tiene
un tratamiento especial para la MATERIALIZED VIEW LOG vinculada con la tabla.
- DELETE
puede utilizarse para eliminar un subconjunto de datos, con TRUNCATE hay que
eliminar todas las filas. Sería bueno que existiera algo así como: TRUNCATE,
WHERE .., no?
- TRUNCATE no
puede mantener foreign keys, por el contrario con DELETE podemos hacer delete
cascade.
- TRUNCATE inválida
índices globales cuando se truncan particiones y subparticiones. Por suerte
desde 9i R2 se pueden mantener los índices globales validos usando UPDATE
GLOBAL INDEXES.
- TRUNCATE
puede validar índices que ya estaban inválidos y pasarlos a estado valido.
Cuidado cuando para acelerar procesos de carga se deshabiliten los índices y
luego se trunque, ya que la carga se hará con los índices habilitados.
Primero truncar y luego pasar los índices a inusables.
- Ni TRUNCATE
ni DELETE de todas las filas eliminan las estadísticas asociadas.
Sería
interesante que se eliminen las estadísticas automáticamente con el TRUNCATE, no?.
- TRUNCATE
invalida los cursores que referencian a la tabla en cuestión.
- DELETE de tablas grandes genera una importante cantidad de UNDO y REDO.
Exclente recopilacion de temas muchas gracias
ResponderEliminarGreat and I have a nifty offer you: Where Is Charlotte Church House Renovation home repairs contractors near me
ResponderEliminar