Category: Tuning / Performance

Utilizando las métricas de Oracle para generar gráficos



Siempre existe la necesidad de mostrar información de manera gráfica, bien lo dice el dicho "Un dibujo vale más que mil palabras" , por ende , mostrar nu gráfico de comportamiento de algún componente de nuestra base de datos, se agradece mucho más que mostrar información de forma plana.

Para ello nos centraremos en la actividad de las vistas relacionadas a las métricas, disponibles desde Oracle10gr1 en adelante



La vista V$SYSMETRIC muestra la métrica de sistema capturada en un intervalo de 15 y 60 segundos , algunos datos importantes en esta vista

V$SYSMETRIC.BEGIN_TIME : Fecha de inicio del intervalo
V$SYSMETRIC.END_TIME : Fecha de término del intervalo
V$SYSMETRIC.INTSIZE_CSEC : Centésimas de segundo en el intervalo
V$SYSMETRIC.METRIC_NAME : Nombre de la métrica
V$SYSMETRIC.VALUE : Valor de la métrica
V$SYSMETRIC.METRIC_UNIT : Descripción de la unidad de medida, en otras palabras , como se calcula el valor de la métrica

La gracia principal de esto es que podemos capturar información de mucha utilidad y generar gráficos "para el jefe" , ¿cómo así? , pues bien ... analicemos un dato que es extremadamente importante y aparece en todos lugares , el Buffer Cache Hit Ratio

Con esta consulta sobre la V$SYSMETRIC podemos consultar el hit ratio del database buffer cache

SQL> r
1 select to_char(BEGIN_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Inicio" ,
2 to_char(END_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Termino" ,
3 INTSIZE_CSEC ,
4 GROUP_ID ,
5 METRIC_ID ,
6 METRIC_NAME ,
7 VALUE ,
8 METRIC_UNIT
9 from v$sysmetric
10* where metric_name like '%Buffer Cache Hit Ratio%'


Y podríamos recopilar información como la que sigue

Fecha Inicio Fecha Termino INTSIZE_CSEC GROUP_ID METRIC_ID METRIC_NAME VALUE METRIC_UNIT
------------------- ------------------- ------------ ---------- ---------- ------------------------- ------- ----------------------------------------
11-11-2009 20:11:15 11-11-2009 20:12:15 6000 2 2000 Buffer Cache Hit Ratio 100.00 % (LogRead - PhyRead)/LogRead
11-11-2009 20:12:45 11-11-2009 20:13:00 1500 3 2000 Buffer Cache Hit Ratio 100.00 % (LogRead - PhyRead)/LogRead


El problema principal (si se le puede llamar problema) es que sólo muestra 2 puntos y con eso, claramente no sabremos la tendencia de nuestra base de datos , por ende necesitamos más puntos, ¿de dónde obtenerlos?, pues del historial de esa vista , la V$SYSMETRIC_HISTORY

1 select to_char(BEGIN_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Inicio" ,
2 to_char(END_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Termino" ,
3 INTSIZE_CSEC ,
4 GROUP_ID ,
5 METRIC_ID ,
6 METRIC_NAME ,
7 VALUE ,
8 METRIC_UNIT
9 from v$sysmetric_history
10 where metric_name like '%Buffer Cache Hit Ratio%'
11* order by 1


Acá nos muestra la última hora de las métricas que necesitamos visualizar , lo cual ya se puede sentir como algo más elaborado , o sea, "les presentamos el comportamiento del Database Buffer Cache durante la última hora" , suena bien , está vista nos entrega información de la última hora con un total de registros de 74

Y si queremos tener una curva algo más prolongada, quizás, el último mes del Database Buffer Cache, pues allí debemos consultar la vista DBA_HIST_SYSMETRIC_HISTORY

La información viaja así ...... después de una hora en memoria en las vistas V$SYSMETRIC y V$SYSMETRIC_HISTORY , el proceso Background MMON descarga la información de estás vistas al diccionario de datos , esa información la encontramos en la vista DBA_HIST_SYSMETRIC_HISTORY

Si piensan un poco , lo anterior es lo que sucede cuando el MMON captura la información estadística desde la SGA , o sea, son los Snapshots del AWR , entre más Snapshots existan , la curva puede ser más amplia cuando analicemos información estadística, que interesante!!!

La forma en que pueden realizar los gráficos mediante la información proveniente de estas tablas, la pueden encontrar muy detallada, paso a paso en el siguiente artículo

B)B)B)Graficar en Excel información proveniente desde StatspackB)B)B)

Hay que extrapolar un poco , la información en este caso no viene del Statspack , proviene de las vistas de Oracle, pero para el caso, es aplicable 500%

¿Qué otra información es útil como métrica?

La verdad muchas otras, como por ejemplo

* CPU Usage Per Sec
* Disk Sort Per Sec
* Host CPU Utilization (%)
* Leaf Node Splits Per Sec
* Library Cache Hit Ratio
* Memory Sorts Ratio
* PGA Cache Hit %
* Physical Reads Per Sec
* Redo Generated Per Sec
* Soft Parse Ratio
* Etc,etc.

La información está , es llegar y graficar :yes:

Mayor descripción de la vista V$SYSMETRIC

De la vista V$SYSMETRIC_HISTORY

Y de la vista DBA_HIST_SYSMETRIC_HISTORY

Espero que les sirva


by Ligarius
20.01.10. 16:40:17. 770 words, 10600 views. Categories: Oracle 11g, Oracle 10g, Tuning / Performance, Oracle11gR2 ,

Oracle11gr1 y Oracle11gr2 : Ha ocurrido un error , ¿Dónde están los logs y traces?



Imagínense el siguiente error

[oracle@SQL]$ sqlplus usuario/password

SQL*Plus: Release 11.2.0.1.0 Production on Thu Dec 10 20:58:22 2009

Copyright (c) 1982, 2009, Oracle. All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> start file
select COUNT(*)
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 887
Session ID: 134 Serial number: 162

SQL>


Tratamos de hacer un trace, se cae, tratamos de generar un evento de traceo , se cae y así , por siempre y para siempre..

Lo mejor es abrir un caso en Oracle, ellos debiesen solucionarlo |-| (no siempre es así, pero les tengo fé)

Y cuando vamos al ORACLE_BASE, nos damos cuenta :>> de que no existe, claro estamos en 11gr2 XX(

Nos colocamos el machete en la boca y nos metemos a los directorios de log y trace (llamado diag) y nos encontramos con muchos de ellos

[oracle@SQL]$ ls -ltr
total 136
drwxr-x--- 2 oracle oinstall 4096 Nov 6 00:17 hm
drwxr-x--- 2 oracle oinstall 4096 Nov 6 00:17 alert
drwxr-x--- 2 oracle oinstall 4096 Dec 10 20:37 metadata
drwxr-x--- 2 oracle oinstall 4096 Dec 10 20:37 ir
drwxr-x--- 4 oracle oinstall 4096 Dec 10 20:58 incident
drwxr-x--- 8 oracle oinstall 12288 Dec 10 20:58 cdump
drwxr-x--- 2 oracle oinstall 4096 Dec 10 20:58 sweep
drwxr-x--- 2 oracle oinstall 20480 Dec 10 20:58 stage
drwxr-x--- 2 oracle oinstall 4096 Dec 10 20:58 lck
drwxr-x--- 4 oracle oinstall 4096 Dec 10 21:09 incpkg
drwxr-x--- 4 oracle oinstall 69632 Dec 10 21:20 trace
[oracle@SQL]$ pwd
/u01/app/oracle/diag/rdbms/inst1/inst1
[oracle@SQL]$


Es ahora donde nos entra la desesperación y nos preguntamos ¿Qué #$"°| le envíamos a Oracle?

Pues bien , allí es donde ingresa el ADRCI, el utilitario para hacernos la vida más fácil con la nueva estructura de diagnóstico que nos provee Oracle

He aquí un pequeño ejercicio

1.- Nos conectamos al adrci

[oracle@SQL]$ adrci

ADRCI: Release 11.2.0.1.0 - Production on Thu Dec 10 21:03:05 2009

Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.

ADR base = "/u01/app/oracle"
adrci>


2.- Verificamos los ORACLE_HOME existente (son mas de 1 ya que estamos trabajando con el DIAG)

adrci> show homes
ADR Homes:
diag/tnslsnr/maq1/listener
diag/rdbms/inst1/inst1
adrci>


3.- Para poder trabajar con el adrci, se debe por obligación seleccionar uno de estos ORACLE HOMES

adrci> set homepath diag/rdbms/inst1/inst1
adrci>
adrci> show homes
ADR Homes:
diag/rdbms/inst1/inst1
adrci>


4.- Una vez seleccionado nuestro ORACLE_HOME, procedemos a ver los "problemas" e "incidentes"
Sólo como introducción , pues generaré un post al respecto, un problema genera múltiples incidentes y un problema es casi siempre crítico, o sea, solucionando el problema se acaban los incidentes (suena a ITIL :)) )

adrci> show problem

ADR Home = /u01/app/oracle/diag/rdbms/inst1/inst1:
*************************************************************************
PROBLEM_ID PROBLEM_KEY LAST_INCIDENT LASTINC_TIME
-------------------- ----------------------------------------------------------- -------------------- ----------------------------------------
1 ORA 7445 [_intel_fast_memcmp()+30] 275 2009-12-10 20:58:26.261000 -03:00
1 rows fetched


5.- Aparece claramente el problema, un error ORA-07445, ahora queremos ver los incidentes que ha originado ese problema

adrci> show incident

ADR Home = /u01/app/oracle/diag/rdbms/inst1/inst1:
*************************************************************************
INCIDENT_ID PROBLEM_KEY CREATE_TIME
-------------------- ----------------------------------------------------------- ----------------------------------------
251 ORA 7445 [_intel_fast_memcmp()+30] 2009-12-10 20:41:07.496000 -03:00
275 ORA 7445 [_intel_fast_memcmp()+30] 2009-12-10 20:58:26.261000 -03:00
2 rows fetched

adrci>

Como se puede apreciar, ha generado varios incidentes , pero sólo necesitamos uno de ellos como para comenzar a procesar la información y poder "empaquetar" todos los archivos necesarios.

6.- Para ello , tomamos el INCIDENT_ID que necesitamos y ejecutamos el siguiente comando

adrci> ips pack incident 275 in /home/oracle
Generated package 2 in file /home/oracle/ORA7445_i_20091210210936_COM_1.zip, mode complete
adrci>


7.- Una vez ejecutado el comando , tenemos un zip con TODA LA INFORMACIÓN necesaria para soporte Oracle y casi ... no nos despeinamos :D

Más información del ADRCI

Espero les sirva...

by Ligarius
14.12.09. 07:39:59. 610 words, 13012 views. Categories: Oracle 11g, Tuning / Performance, Oracle11gR2 ,

Strace : Comando para hacer debug a bajo nivel en Linux...



strace es un utilitario que sirve para hacer un trace a un comando en partícular, suena sencillo... pero es un potente amigo :)

Disponible en ambientes Linux, es una gran herramienta para buscar el porque algún comando en partícular falla.

Cada vez que strace ejecuta algún comando , puede registrar todos los archivos utilizados y el comando ejecutado en un stack, el cual puede ser ubicado en un archivo de salida.



Para generar cualquier salida con strace lo ejecutamos de la siguiente forma.
Eje:

[oracle@oracle10g oracle]$ strace -o salida.txt lsnrctl start LISTENR
[oracle@oracle10g oracle]$ ls -ltr salida.txt
-rw-r--r-- 1 oracle oinstall 65910 Dec 6 09:26 salida.txt


Cada vez que sucede un error casi siempre aparece un -1 con la descripción del error dentro del archivo generado en el punto anterior.
Eje:

2236 stat64("/u01/app/oracle/product/10.1.0/db_1/lib/tls", 0xbfff8bf0) = -1 ENOENT (No such file or directory)


Incluso se le puede agregar la fecha del día a cada línea de salida de strace
Eje:

strace -t -o salida.txt lsnrctl start LISTENR

more salida.txt
09:29:54 execve("/u01/app/oracle/product/10.1.0/db_1/bin/lsnrctl", ["lsnrctl", "start", "LISTENR"], [/* 29 vars */]) = 0
09:29:54 uname({sys="Linux", node="oracle10g.inmotion.cl", ...}) = 0
09:29:54 brk(0) = 0x8f75000


Incluso con microsegundos
Eje:

[oracle@oracle10g oracle]$ strace -tt -o salida.txt lsnrctl start LISTENR

[oracle@oracle10g oracle]$ more salida.txt
09:30:46.284985 execve("/u01/app/oracle/product/10.1.0/db_1/bin/lsnrctl", ["lsnrctl", "start", "LISTENR"], [/* 29 vars */]) = 0
09:30:46.286140 uname({sys="Linux", node="oracle10g.inmotion.cl", ...}) = 0
09:30:46.286579 brk(0) = 0x928d000


Si se quiere saber en microsegundos la duración de cada proceso interno ejecutado por el strace (según el comando ingresado)
Eje:

[oracle@oracle10g oracle]$ strace -tt -T -o salida.txt lsnrctl start LISTENR

09:31:36.680126 execve("/u01/app/oracle/product/10.1.0/db_1/bin/lsnrctl", ["lsnrctl", "start", "LISTENR"], [/* 29 vars */]) = 0 <0.000425>
09:31:36.681208 uname({sys="Linux", node="oracle10g.inmotion.cl", ...}) = 0 <0.000073>
09:31:36.681608 brk(0) = 0x9b6e000 <0.000072>


Incluso se puede fitrar por tipo de ejecución del comando ejecutado por el strace
Eje:

Para saber sólo los comandos asociados a la red
strace -tt -T -e trace=network -o salida.txt lsnrctl start LISTENR


Para saber sólo los comando ejecutados, pero que reciban como parámetro un archivo
Eje:

strace -tt -T -e trace=file -o salida.txt lsnrctl start LISTENR


Incluso se le puede indicar algún PID de sistema operativo que ya se encuentre en ejecución
Eje:

strace -tt -T -p 18909 -o salida.txt lsnrctl start LISTENR


Espero les sirva

by Ligarius
10.12.09. 07:30:08. 414 words, 15049 views. Categories: Base de datos, Tuning / Performance, Linux ,

Oracle10gr2 : Disminuyendo el LOG FILE SYNC con COMMIT NOWAIT


Para comenzar la charla , les pido disculpas por el tiempo alejado de las canchas, pero fue única y exclusivamente por la carga de trabajo que tenía en mi empresa, de hecho hoy en día me encuentro dictando dos cursos por día :

- Horario de tarde : WorkShop II Ed 3 de Oracle10g
- Horario de noche : Oracle Reports Builder 11g

Así que imagínense el tiempo que tengo, pero bueno... a lo que vinimos...



El evento de espera LOG FILE SYNC se da cuando una sesión de usuario ejecuta un final de transacción por ejemplo un COMMIT o un ROLLBACK , la información almacenada en el Log Buffer para esa transacción necesita ser envíada a disco , especificamente a los archivos de redolog, cuando está finaliza , la sesión recién comienza a generar otras actividades, en otras palabras, cuando se ejecuta un término de transacción la sesión entra en un evento de espera, que está relacionado al tiempo que demora el LGWR en escribir las entradas del log buffer (en realidad son vectores, pero es materia de otro Post) hacía los redologs, cuando eso finaliza .. la transacción se acepta como válida.


A veces , cuando la aplicación es muy transaccional , el LOG FILE SYNC , aparece como un Top 5 dentro del Statspack o dentro un AWR Rpt, cuando sucede eso, hay formas de mejorar esos tiempos de respuesta.



Observación : No se recomienda llevar a cabo estos cambios sin la visación de Oracle Support




Ejecución de commit asincrónico

Como ya vimos el proceso del commit y como se vaciaban los registros desde el Log Buffer , pasamos a señalar el como ejecutar el commit asincrónico para solucionar el evento de espera LOG FILE SYNC


El comando commit posee variaciones , las cuales se pueden apreciar en el siguiente detalle
WAIT : No se retorna el mensaje de commit exitoso hasta que las entradas del LogBuffer hayan sido escritas a los redo logs

NOWAIT : El commit puede retornar el control a la aplicación aunque aún la sentencia no este registrada a los archivos de redologs, lo cual puede resultar algo peligroso.

IMMEDIATE : El proceso LGWR escribe de forma inmediata la entrada de la transacción presente en los log buffer hacía los redo logs, en otras palabras , se fuerza un I/O

BATCH : Este modo le indica a Oracle que a pesar de haber finalizado la transacción con un commit, la bajada de los vectores desde el log buffer se produzca en el ciclo normal del log buffer , por ejemplo , cuando se llena a un tercio

Por defecto , cuando ustedes ejecutan el commit se ejecuta con WAIT IMMEDIATE , pero esto se puede modificar ejecutando la siguiente sentencia

COMMIT WRITE NOWAIT IMMEDIATE , o sea, no espera a que se escriba la información del log buffer a los redo logs, entrega el control a la aplicación y hace la bajada de la información del log buffer de forma inmediata a los redo logs

Es una opción que hay que manejar con cuidado , pues puede haber pérdida de datos , por ejemplo este comando

COMMIT WRITE NOWAIT BATCH , puede dejar mucha información en memoria , indicarles que se hizo el commit exitoso y ante una caída quedar con información inconsistente.

Todo lo anterior también se puede setear mediante el parámetro de incialización correspondiente

COMMIT_WRITE

Y analizando toda esta información , para solucionar en parte el evento de espera LOG FILE SYNC , se podría cambiar el modo del commit para los procesos batch de la siguiente forma

COMMIT WRITE NOWAIT BATCH

Espero que les haya servido

Documentación necesaria
Parámetro COMMIT_WRITE
Evento de espera LOG FILE SYNC


by Ligarius
02.12.09. 13:23:18. 632 words, 7361 views. Categories: Oracle 11g, Oracle 10g, SQL / Programación, Tuning / Performance ,

Oracle11gr2 : Claúsula IGNORE_ROW_ON_DUPKEY_INDEX , para evitar los errores ORA-0001



Si tenemos una tablaA la cual contiene datos y una tablaB con la misma estructura pero con otros datos , y queremos fusionarla, ¿Cómo lo hacemos sin que haya registros repetidos? , o mejor dicho, ¿Cómo lo hacemos para que no se gatille la Primary Key?



Pues bien , lo podríamos hacer con un Pl/Sql de la siguiente forma :

declare
cursor c1 is select ...
begin
open c1
loop
exit when c1 not found
fetch c1 into variable
end loop;
end;

O podría ser con un FOR ... LOOP , pero en el fondo , debemos generar código sí o sí :-/

Pues bien , Oracle11gr2 , nos soluciona ese inconveniente , ¿cómo?

Ha creado una gran claúsula llamada IGNORE_ROW_ON_DUPKEY_INDEX , que no es nada más que in hint :>> , acá viene su uso...

1.- Creamos la tabla que contiene los datos originales y que contiene la PK

SQL> create table tabla1 (col1 number not null ,
2 col2 number not null ,
3 col3 date ,
4 constraint tabla1_pk primary key (col1));

2.- Insertamos datos sencillos dentro de la tabla, sin violar la PK

SQL> insert into tabla1 values (1,1,sysdate);

1 row created.

SQL> insert into tabla1 values (2,1,sysdate);

1 row created.

SQL> insert into tabla1 values (3,1,sysdate);

1 row created.

3. - Insertamos un valor con el format INSERT VALUES y veremos como se gatilla la Primary Key

SQL> insert into tabla1 values (1,0,sysdate);
insert into tabla1 values (1,0,sysdate)
*
ERROR at line 1:
ORA-00001: unique constraint (SYS.TABLA1_PK) violated

4.- Procedemos a insertar la misma fila, pero con el hint IGNORE_ROW_ON_DUPKEY_INDEX , y vemos el resultado , que no inserta la fila y no arroja error :)

SQL> insert /*+ ignore_row_on_dupkey_index (tabla1 (col1) ) */
2 into tabla1 values (1,0,sysdate);

0 rows created.

¿Qué sucede con el formato de inserción INSERT SELECT? , pues bien acá un ejemplo

5.- Vemos la tabla secundaria y los datos que contiene, los cuales no pueden ser insertados en su totalidad pues violan la PK

SQL> select * from valores_tmp;

CAMPO1 CAMPO2
---------- ----------
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8

6 .- Procedemos a insertar sin ocupar el nuevo HINT y aparece el típico error de violación de PK

SQL> insert into tabla1 (select campo1 , campo2 , sysdate from valores_tmp);
insert into tabla1 (select campo1 , campo2 , sysdate from valores_tmp)
*
ERROR at line 1:
ORA-00001: unique constraint (SYS.TABLA1_PK) violated

7.- Y si consultamos los datos de nuestra tabla original, vemos que no han sido afectados

SQL> select * from tabla1;

COL1 COL2 COL3
---------- ---------- ---------
1 1 05-SEP-09
2 1 05-SEP-09
3 1 05-SEP-09

SQL>

8.- Ahora si insertamos los mismos datos, pero con la nueva claúsula , vemos como ocurre la magia, simplemente selecciona cuales insertar ... que bien :>>

SQL> insert /*+ ignore_row_on_dupkey_index (tabla1 (col1) ) */
2 into tabla1 (select campo1 , campo2 , sysdate from valores_tmp);

5 rows created.

SQL>

9.- Validamos nuevamente nuestra tabla original y están los datos correctos, de ambas tablas

SQL> select * from tabla1;

COL1 COL2 COL3
---------- ---------- ---------
1 1 05-SEP-09
2 1 05-SEP-09
3 1 05-SEP-09
4 4 05-SEP-09
5 5 05-SEP-09
6 6 05-SEP-09
7 7 05-SEP-09
8 8 05-SEP-09

8 rows selected.

SQL>

Espero les sirva

by Ligarius
06.09.09. 14:48:21. 500 words, 5699 views. Categories: Base de datos, Tuning / Performance, Oracle11gR2 ,

<< 1 2 3 4 5 6 7 8 >>