martes, 9 de agosto de 2011

UNDO SEGMENT TUNING & DEFINICION


INTRODUCCION

A partir de la versión 9i de Oracle el UNDO SEGMENT entró a reemplazar a los ROLLBACK SEGMENTS que cumplían con la misma tarea, pero el UNDO SEGMENTS necesita de menor administracion que los ROLLBACK SEGMENT.  Esto es gracias a que el UNDO SEGMENT tiene una gestión automática.

Por que usar UNDO SEGMENT en vez del ROLLBACK SEGMENT?
Oracle siempre busca a la gestión automática de estos segmentos y esto se logra gracias a la gestión automática del UNDO SEGMENT, indicando cual es el tablespace UNDO para cada instancia de base de datos. Con los ROLLBACK SEGMENT hay que definir cada uno de estos segmentos para cada tablespace.


La tarea del UNDO SEGMENT es garantizar la integridad de los datos que son:

o   Transaction Rollback( Deshacer transacciones): Guardar en el UNDO SEGMENT los regisros de datos antes de la modificación. Si la transacción es deshecha (Rollback)  los registros se restablecen con la imagen  almacenada en el UNDO SEGMENT para revertir los cambios no confirmados.

o   Transaction Recovery( Recuperación de transacciones) : Esto en los caso de que la base de datos Oracle falla, todas las transacciones en progreso y no confirmadas deben de revertirse.

o   Read Consistency( Lectura Consistente): Oracle mantiene el concepto de lectura consistente y esto consiste en que muchos usuarios están accesando simultáneamente a los datos. Cada sesión de usuario no presentara a las demás sesiones de usuarios los cambios realizado de los datos hasta que los confirme (commit). De esto se trata la consistencia, mantener oculto las modificaciones de datos a las demás sesiones de usuarios hasta que las confirme.

o   Apoya a la generación de consultas SQL complejas que necesitan crear temporalmente bloques de datos en el UNDO_SEGMENT. Si tenemos un reporte o consulta muy compleja que necesita de mucha información, Oracle se apoyará del UNDO_SEGMENT para armar el set de información requerido.

Lectura consistente de datos
 En la imagen "Lectura consistente de datos", se muestra cuando una sesion de usuario realiza modificaciones a la tabla employee, en la tabla se realiza el cambio realizado por el update, pero antes se saca una imagen del dato (Undo image) para almacenarlo en el UNDO SEGMENT, las demas sesiones de usuarios que intenten accesar a los datos de la tabla employee no leeran los datos modificados en la tabla si no de la imagen almacenda en el UNDO SEGMENT, esto se realizara hasta que la sesion que modifique realice un commit o rollback. 
Si se realiza un commit, se liberará el segmento de UNDO usado.
Si se realiza un rollback, se reversará el cambio realizado en la tabla employee copiando la imagen respaldada en el UNDO SEGMENT a la tabla y posterior a eso se liberar el segmento de UNDO usado.

ADMINISTRACION AUTOMATICA DEL UNDO

Crear el tablespace tipo UNDO.
CREATE UNDO TABLESPACE UNDOTBS2
DATAFILE '+DATA' SIZE 12400M
AUTOEXTEND ON NEXT 100M MAXSIZE UNLIMITED
ONLINE;

UNDO_MANAGEMENT
Hay que cambiar la configuración a gestión automática la administración del UNDO, esto se logra cambiando el parámetro de base de datos UNDO_MANAGEMENT;
ALTER SYSTEM SET UNDO_MANAGEMENT =AUTO SCOPE=SPFILE;
SHUTDOWN IMMEDIATE;
STARTUP;

UNDO_TABLESPACE
Configurar cual es el tablespace UNDO.
ALTER SYSTEM SET UNDO_TABLESPACE =UNDOTBS2 SCOPE=BOTH;

UNDO_RETENTION
Este parámetro viene configurado por defecto con 900 (15 minutos ) medido en segundos y especifica el tiempo que el segmento perdurará en el UNDO SEGMENT antes de ser liberado para ser reutilizado.

TUNEA LOS PARAMETROS DEL UNDO SEGMENT.

Cuáles son los parámetros ideales?
No existe una configuración inicial perfecta con la que podamos iniciar, pero si podemos afinarla con el transcurso del tiempo y es una tarea del DBA obtener el valor optimo para el mejor desempeño de la base de datos.

NOTA: Estas evaluaciones, deberán realizarse después de un periodo de operación de la base para que las estadiscas tengan la suficiente información como para dar un resultado adecuado. Esto por los casos en que es una base de datos que arranca su operación y se quiera estimar estos valores.

Cuál es el valor ideal para el UNDO_RETENTION?
Para esto podemos usar la siguiente fórmula:

Fórmula para determinar cual es el valor ideal para el UNDO_RETENTION

ALTER SYSTEM SET UNDO_RETENTION =300 SCOPE=BOTH;

Donde:
ACTUAL TAMAÑO DEL UNDO
SELECT SUM (a.bytes) / 1024 / 1024 "MB TAMAÑO ACTUAL UNDO"
  FROM  v$datafile a,
        v$tablespace b,
        dba_tablespaces c
 WHERE     c.contents = 'UNDO'
       AND c.status = 'ONLINE'
       AND b.name = c.tablespace_name
       AND a.ts# = b.ts#;

UNDO_BLOCK_PER_SEC: Cantidad de bloques undo que se transfieren por segundo
SELECT MAX(undoblks/((end_time-begin_time)*3600*24))
      "UNDO_BLOCK_PER_SEC"
  FROM v$undostat; 

DB_BLOCK_SIZE: Tamaño del bloque de datos que maneja la base.
SELECT TO_NUMBER(value) "DB_BLOCK_SIZE KB"
 FROM v$parameter
WHERE name = 'db_block_size';

VALOR OPTIMO PARA EL UNDO RETENTION
SELECT d.undo_size/(1024*1024) "ACTUAL UNDO SIZE MB",
       SUBSTR(e.value,1,25) "ACTUAL UNDO RETENTION [Sec]",
       ROUND((d.undo_size / (to_number(f.value) *
       g.undo_block_per_sec))) "SUGERIDO UNDO RETENTION [Sec]"
  FROM (
       SELECT SUM(a.bytes) undo_size
          FROM v$datafile a,
               v$tablespace b,
               dba_tablespaces c
         WHERE c.contents = 'UNDO'
           AND c.status = 'ONLINE'
           AND b.name = c.tablespace_name
           AND a.ts# = b.ts#
       ) d,
       v$parameter e,
       v$parameter f,
       (
       SELECT MAX(undoblks/((end_time-begin_time)*3600*24))
              undo_block_per_sec
         FROM v$undostat
       ) g
WHERE e.name = 'undo_retention'
  AND f.name = 'db_block_size'

Cuál es el tamaño ideal para el tablespase UNDO?
Fórmula para determinar el tamaño ideal del UNDO TABLESPACE
 Se deberá modificar el tamaño del tablespace con el valor recomendado.
SELECT d.undo_size/(1024*1024) "TAMAÑO ACTUAL UNDO MB",
       SUBSTR(e.value,1,25) "UNDO RETENTION [Sec]",
       (TO_NUMBER(e.value) * TO_NUMBER(f.value) *
       g.undo_block_per_sec) / (1024*1024)
      "TAMAÑO UNDO NECESARIO MB"
  FROM (
       SELECT SUM(a.bytes) undo_size
         FROM v$datafile a,
              v$tablespace b,
              dba_tablespaces c
        WHERE c.contents = 'UNDO'
          AND c.status = 'ONLINE'
          AND b.name = c.tablespace_name
          AND a.ts# = b.ts#
       ) d,
      v$parameter e,
       v$parameter f,
       (
       SELECT MAX(undoblks/((end_time-begin_time)*3600*24))
         undo_block_per_sec
         FROM v$undostat
       ) g
 WHERE e.name = 'undo_retention'
  AND f.name = 'db_block_size'

Si el valor recomendado es menor al tamaño actual, estara a criterio del DBA disminuir el tamaño o en su defecto aumentar el UNDO_RETENTION, por que a mayor tamaño de lo necesario, mayor tiempo de retención podemos especificar.

ERRORES QUE SE PUEDEN PRESENTAR RELACIONADOS CON EL UNDO SEGMENT.

ORA-30036: Unable to extend segment by nombre_segmento in undo tablespace nombre_tablespace

CAUSA
Este error pasa cuando el tamaño del UNDO TABLESPACE se agotó y no se pueden crear nuevos segmentos.
El parámetro UNDO RETENTION tiene un valor muy elevado que no deja liberar los segmentos del UNDO_SEGMENT para que sean reutilizados.

SOLUCION
Aumentar el tamaño al UNDO TABLESPACE y como recomendación habilitar el AUTO EXTENT con un valor  del 10% de tamaño del tablespace.
Analizar el tamaño del UNDO_RETENTION y evaluar disminuir el tamaño.

ORA-30019:  Illegal rollback segment operation in Automatic Undo mode

CAUSA
Esto ocurre cuando tratamos  con ROLLBACK SEGMENT en bloque PL/SQL (Es una programación antigua donde se usa el comando “SET TRANSACTION USE ROLLBACK SEGMENT”) y la base de datos Oracle está configurada  en administración automática del UNDO.

SOLUCION
Oracle permite coexistir al UNDO SEGMENT y el ROLLBACK SEGMENT para mantener la compatibilidad con versiones anteriores de Base de datos, pero para esto se deberá configurar el parámetro de base de datos UNDO_SUPPRESS_ERRORS=TRUE.
Si no desea realizar esta configuración, se debera cambiar la linea de código que hace el seteo del ROLLBACK SEGMENT.

ORA-1555 snapshot too old

CAUSA
Esto ocurre cuando Oracle no puede lograr una lectura consistente de los datos. Alguna sesión trata de accesar a datos que deberían encontrarse en la UNDO SEGMENT, pero no los encuentra.

SOLUCION
Se deberá evaluar el valor con el que se deberá aumentar el UNDO_RETENTION para poder mantener la lectura consistente.

sábado, 6 de agosto de 2011

TIP'S PARA EL TUNING DE TU SQL

En ocasiones no solo basta con realizar un buen afinamiento a la base de datos Oracle para mejorar el rendimiento.  Podemos hacer que mejore el rendimiento aplicando buenas prácticas al realizar nuestros SQL y PL/SQL.

A continuación les indicaré unos tips que pueden usar para las buenas prácticas en el desarrollo.

USAR VARIABLES BIND:

Esto es sobre todo en aplicaciones desarrollo de aplicaciones JAVA, .NET, VSB6, VFP, PHP, Etc. Ya que la las herramientas developer de Oracle no ocurre mucho.

Para esto primero entendamos que:

·         El análisis de una sentencia SQL y averiguar su plan de ejecución óptimo consumen mucho tiempo para Oracle, por eso Oracle mantiene las sentencias SQL en memoria después de haber analizado y ejecutado la sentencia SQL para reutilizar no realizar de nuevo el análisis y usar el plan de ejecución definidos en su primera ejecución.
·         Oracle antes de realizar el análisis primero busca la librería SQL el contexto (SGA) para ver si hay una declaración idéntica existente.
·         Para que una sentencia SQL sea compartida debe de ser idéntica en todo sentido de la palabra.

Veamos un ejemplo,
·     Aunque las siguientes sentencias hagan lo mismo no son iguales, ya que el analizador es sensible a las mayúsculas y minúsculas:
Select * from empleados where numero_empleado=2012;
SELECT * FROM EMPLEADOS WHERE NUMERO_EMPLEADO=2012;

·     Las dos sentencias SQL no son idénticas ya que el filtro en el campo NUMERO_EMPLEADO son diferentes, por lo que durante su ejecución las dos sentencias se analizaran y planificaran como diferentes:
SELECT * FROM EMPLEADOS WHERE NUMERO_EMPLEADO=2012;
SELECT * FROM EMPLEADOS WHERE NUMERO_EMPLEADO=2013;

·     Para optimizar la ejecución de estas dos sentencias debemos usar en lo posible las variables bind
SELECT * FROM EMPLEADOS WHERE NUMERO_EMPLEADO=:NUM_EMP;

Si desean pueden ver mas a fondo de este tema con ejemplos en el siguiente link 

USAR WHERE EN VEZ DE HAVING:
El evitar el uso del HAVING en la instrucción SELECT. Las condiciones del HAVING son de exclusividad para funciones agregadas como el COUNT, SUM, AVG, MAX, MIN, etc y no son para condiciones de datos.

·    Si usamos el HAVING se extraerán todos los datos y luego se realizara el agrupamiento con el filtrado de los datos.

SELECT OWNER,OBJECT_TYPE, COUNT(*)
FROM ALL_OBJECTS
GROUP BY OWNER,OBJECT_TYPE
HAVING OWNER='SYSTEM';
·     En cambio con el WHERE se filtran los datos y luego se realice el agrupamiento, siendo esto menos costoso.

SELECT OWNER,OBJECT_TYPE, COUNT(*)
FROM ALL_OBJECTS
WHERE OWNER='SYSTEM'
GROUP BY OWNER,OBJECT_TYPE;


USAR UNION ALL EN VEZ DEL UNION
·     Con la clausula UNION se realizará un ordenamiento para obtener  filas distintas y eliminar las repetidas, un ordenamiento es un costo adicional en el procesamiento de la CPU.
SELECT *
FROM ALL_TABLES
UNION
SELECT *
FROM DBA_TABLES;


·     Con la clausula UNIOM ALL no se realiza ordenamiento ni eliminación de las filas repetidas, lo que hace es unir tal como vengan los datos de las sub-consultas.
SELECT *
FROM ALL_TABLES
UNION ALL
SELECT *
FROM DBA_TABLES


USAR EXISTS O NOT EXISTS EN VEZ DE IN O NOT IN
Es mejor usar la clausula EXISTS en vez del IN, esto ya que al usar el EXISTS es como si realizaramos el JOIN entre las tablas. El uso de la clausula IN es recomendable si el dominio de datos es pequeño (a mi criterio que no pase de 100 registros).

·         Veamos el ejemplo con el NOT IN.
SELECT * FROM ALL_OBJECTS
WHERE OBJECT_ID NOT IN (SELECT OBJECT_ID
                        FROM USER_OBJECTS);


·         Veamos el ejemplo con el NOT EXISTS.
SELECT * FROM ALL_OBJECTS A
WHERE NOT EXISTS (SELECT 1 FROM USER_OBJECTS B
                  WHERE A.OBJECT_ID=B.OBJECT_ID );


viernes, 15 de julio de 2011

Perfiles del SQLNET.ORA


Alguna vez se han preguntado qué utilidad le podemos dar al archivo SQLNET.ORA?

Este archivo por defecto se crea en la ruta %ORACLE_HOME%\network\admin, la configuración que realicemos en este archivo nos ayudará a:

Controlar el acceso a la base de datos por medio del protocolo de red, métodos de autenticación, definir los tiempos de comprobación de actividad de las sesiones de los clientes.

Estas son unas cuantas de las utilidades de SQLNET.ORA, y continuación le explicaré unas muy útiles.

SQLNET.EXPIRE_TIME

Este parámetro esta medido en minutos y es usado para especificar el intervalo de tiempo de envió de test a la conexiones clientes/servidor para comprobar si están activas. Este es un método que garantiza que las conexiones a la base de datos no se dejen abiertas indefinidamente, esto es una manera. Este parámetro por defecto esta seteado con cero pero es recomendable que se configure con valor superior a cero (Yo lo tengo configurado con 10).

Este parámetro podría solucionarles problemas de desconexión de los clientes a la base de datos para los problemas de redes intermitentes o desconexiones momentáneas de la red.

Me paso que me llegaban reportes de quejas de usuarios por las constantes desconexiones que sufrían, luego procedí a configurar este parámetro y las quejas disminuyeron no desaparecieron (Habían otros problemas) pero en su mayoría sí.

Consideraciones:

La configuración de un valor muy bajo podría traer consecuencias en el rendimiento de la red por el tráfico que se generaría para realizar las comprobaciones.

Ejemplo:
#Por Defecto: 0

#Mínimo : 0

#Recomendado: 10

SQLNET.EXPIRE_TIME=10


TCP.EXCLUDED_NODES

Nos permite indicar que clientes no podrán establecer conexión a la base de datos. Se puede definir por la ip o nombre de la máquina.

Consideraciones:

Si lo configuran deben de asegurarse que los host o ip a excluir no estén los procesos de respaldos, repositorio +ASM, etc.

Sintaxis:

TCP.EXLCUDED_NODES=(hostname | ip_address, hostname | ip_address, ...)


  Ejemplo:

#Se deniega las conexiones a la base desde la ip 192.168.1.133 y al host pccliente05

tcp.validnode_checking =yes

tcp.excluded_nodes = (192.168.1.133,pccliente05)

 

TCP.INVITED_NODES

Nos permite indicar que clientes podrán establecer conexión a la base de datos. Se puede definir por la ip o nombre de la máquina.

Consideraciones:

Si lo configuran deben de asegurarse que todos hosts o ip de servicios o clientes que deban establecer conexión a la base de datos como procesos de respaldos, repositorio +ASM, etc.

Sintaxis:

TCP.INVITED_NODES=(hostname | ip_address, hostname | ip_address, ...)


 

Ejemplo:

#Se permite las conexiones a la base desde la ip 192.168.1.134 , las conexiones locales y al host pccliente01

tcp.validnode_checking =yes

tcp.invited_nodes = (192.168.1.134, localhost, pccliente01)

 

TCP.VALIDNODE_CHECKING

Nos permite habilitar la validación de la configuración TCP.INVITED_NODES y TCP.EXCLUDED_NODES.

Consideraciones:

Si el valor de TCP.VALIDNODE_CHECKING no está seteado en yes entonces no tiene efecto la configuración de TCP.INVITED_NODES y TCP.EXCLUDED_NODES.

Ejemplo:

#Por Defecto: no

#Permitido : yes, no

tcp.validnode_checking =yes

   

NOTA:

Si modificas el archivo SQLNET.ORA para que se apliquen los cambios deberás reiniciar el servicio del listener o recargar la configuración.

Ejemplo:

##Recargando la configuración

C:\>lsnrctl

LSNRCTL for 32-bit Windows: Version 10.2.0.4.0 - Production on 15-JUL-2011 18:47:06

Copyright (c) 1991, 2007, Oracle. All rights reserved.

Welcome to LSNRCTL, type "help" for information.

LSNRCTL> reload

The command completed successfully

 

##Reiniciar

C:\>lsnrctl

LSNRCTL for 32-bit Windows: Version 10.2.0.4.0 - Production on 15-JUL-2011 18:47:06

Copyright (c) 1991, 2007, Oracle. All rights reserved.

Welcome to LSNRCTL, type "help" for information.

LSNRCTL> stop

The command completed successfully

LSNRCTL> start

The command completed successfully

lunes, 13 de junio de 2011

Parámetro db_writer_processes

Como podemos optimizar el proceso de escritura del SGA a los archivos de datos?

La respuesta la encontramos en el parámetro de base de datos db_writer_processes, quien es el que indica el número de procesos que el RDBMS de Oracle debe de levantar para escribir ta disco todos los cambios realizados en la SGA.


Gráfico de la arquitectura del Oracle Server
Como vemos en la gráfica del Oracle Server, se que el proceso Database Writer es el encargado de escribir a disco todos los cambios realizados en la SGA.

Este parámetro por defecto es 1 y el valor que se le pueda asignar va a depender de la cantidad de procesadores en el que este levantado el RDBMS de Oracle. El rango de valores que admite es de 1 a 20 para versiones de Oracle 10g y de 1 a 32 para Oracle 11g.

Para ver como esta configurado el parámetro db_writer_processes:
  • select name, value from v$parameter where name='db_writer_processes';
  • show parameter db_writer_processes;
Para cambiar el parámetro db_writer_processes:
  • alter system set db_writer_processes=valor_asignar scope=SPFILE
Nota: Al cambiar este parámetro se deberá reinicar la base de datos.
Si tu base e datos es muy transaccional entonces puedes modificar el parámetro db_writer_processes al número de procesadores que tenga el servidor en donde esta levantado el RDBMS de Oracle.

Ejemplo:
Supongamos que tenemos nuestra bas de datos en un servidor con 4 procesadores y deseamos setear el mismo número de procesos writer en nuestra base de datos.

//Seteamos en la variable de ambiente la instancia
>set oracle_sid=capacitacion

//Nos conectamos a la base como sys
>sqlplus / as sysdba

//Revisamos como esta seteado el parametro antes del cambio
SQL> show parameter db_writer_processes;
NAME                 TYPE        VALUE
-------------------- ----------- ------------------------------
db_writer_processes  integer     1


//Ateramos el parametro a 4
SQL> alter system set db_writer_processes=4 scope=SPFILE;
System altered.

//Bajamos la instancia
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.

//Iniciamos la instancia
SQL> startup;
ORACLE instance started.
Total System Global Area 1610612736 bytes
Fixed Size                  1299316 bytes
Variable Size             285215884 bytes
Database Buffers         1317011456 bytes
Redo Buffers                7086080 bytes
Database mounted.
Database opened.

//Revisamos como quedo seteado el parametro antes del cambio
SQL> show parameter db_writer_processes;
NAME                 TYPE        VALUE
-------------------- ----------- ------------------------------
db_writer_processes  integer     4

sábado, 11 de junio de 2011

Forzar el uso de variables bind con el parámetro CURSOR_SHARING

Como evitar HARD PARSE al momento de que nuestro sistema ejecuta sentencias SQL que no usan Variables Bind?

Recordemos que al existir gran cantidad HARD PARSES, el tiempo de respuesta y rendimiento de la base de datos se  degrada, ademas del llenado del area SQL LIBRARY del SGA. Lo ideal es que no existan demasiados Hard Parse si no Soft Parse.

En mi nota anterior se explicó la forma de optimizar el rendimiento y tiempo de respuesta al momento de ejecutar una sentencia SQL usando variables bind en la programación, pero en ocasiones no es fácil aplicarlo ya que los DBA o Lideres de progrmadores no desarrollamos toda la aplicación o no realizamos un control de calidad para ver que se cumplan estos estandares. Otro motivo es que así compramos el sistema y no lo desarrollamos!

Para esto debemos modificar la programación. Una tarea muy dura, no?

Pues la respuesta a este problema es cambiar el parámetro de base de datos CURSOR_SHARING.
Oracle tiene el parámetro de base de datos CURSOR_SHARING que por defecto esta configurado con EXACT.

Y esto en que me ayuda? El CURSOR_SHARING admite 3 valores: EXACT, SIMILAR y FORCE

EXACT Valida que la sentencia SQL a ejecutarse sea exactamente igual a la que existe en la librería SQL para que no se realice un HARD PARSE. Ejemplo

Las siguietes dos sentencia hacen consulta sobre el mismo objeto, son casi iguales pero el valor de filtro para el campo cédula son diferentes por lo que hace que las dos sentencias sean diferentes y cada una se ejecute por un HARD PARSE
--Sentencia en la librería SQL
select * from persona where cedula='0123456789';
--Sentencia a ejecutar
select * from persona where cedula='0000000000';

SIMILAR
Valida que la sentencia SQL sean similares a nivel de select, from y where pero los valores constantes son reemplazados con variables, es decir la tarea que no realizamos anivel de programación.

Con el parámetro en SIMILAR estas dos sentencias son iguales y no se realizará HARD PARSE al momento de ejecutarse.
--Sentencia en la librería SQL
select * from persona where cedula='0123456789'; => select * from persona where cedula="VAR_1";
--Sentencia a ejecutar
select * from persona where cedula='0000000000'; => select * from persona where cedula="VAR_1";

FORCE
Es parecido al parámetro SIMILAR si no que la diferencia es que SIMILAR no registrará en la librería SQL la sentencia evaluada evitando el llenado de la misma.

Si no quedó claro, imaginense que ejecutamos 10000 consultas de personas por el número de de cédula y estos número de cédula son diferentes y no usan variable bind. en CUSRSOR_SHARING igual SIMILAR solo se registraría una vez la sentencia en la librería SQL la sentencia. En FORCE se registrarían
10000 veces la sentecia en la librería SQL.

Veamos el ejemplo
Consultas sin variables bind con parámetro CURSOR_SHARING=EXACT
--Vemos que este configurado el parámetro como  EXACT
show parameter cursor_sharing;
cursor_sharing                       string   EXACT

-- Liberamos la memoria shared pool
Alter System Flush Shared_Pool;
System Switch Log Altered.
Elapsed: 00:00:00:01

--Escript que realizará las consultas sin variables BIND
Declare
  C_Cedula Varchar2(20);
  N_Can       Number;
  C_Sql    Varchar2(200);
Begin
  For N_Id In 1..10000 Loop
    C_Cedula:=N_Id;
    C_Sql:='SELECT COUNT(*) FROM PERSONAS WHERE IDENTIFICACION='''||N_Id||'''';
    Execute Immediate C_Sql Into N_Can;
  End Loop;
End;

Elapsed: 00:00:04:68
-- Revisamos la cantidad de sentencias almacenadas en la librería SQL
Select Count(*) Cantidad From V$Sql
Where Sql_Text Like 'SELECT COUNT(*) FROM PERSONAS WHERE IDENTIFICACION=%';
  Cantidad
----------
     10000
Elapsed: 00:00:00:15


Ahora analicemos como esta la memoria

Gráfica de uso de la memoria SHARED POOL

Vemos como se vio afectada el tamaño disponible del Share Pool y el tamaño de la Sql Area aumentó por las 10,000 consultas SQL almacenadas en sentencias dentro de la Sql Library, esto representa 10,000 Hard Parse y 0 Soft Parse (Esto es malo para el Oracle Server).. El tiempo de ejecución fue de 4.68 segundos

Consultas sin variables bind con parámetro CURSOR_SHARING=SIMILAR

--Cambiamos el parámetro de base de datos CURSOR_SHARING=SIMILAR
alter system set cursor_sharing = SIMILAR scope=BOTH;

connect vendara/vendara
--Vemos que este configurado el parámetro como SIMILAR
show parameter cursor_sharing;
cursor_sharing                       string   SIMILAR


-- Liberamos la memoria del la shared pool
Alter System Flush Shared_Pool;
System switch log altered.

set timing on;
--Escript que realizará las consultas sin variables BIND
Declare
  C_Cedula Varchar2(20);
  N_Can       Number;
  C_Sql    Varchar2(200);
Begin
  For N_Id In 1..10000 Loop
    C_Cedula:=N_Id;
    C_Sql:='SELECT COUNT(*) FROM PERSONAS WHERE IDENTIFICACION='''||N_Id||'''';
    Execute Immediate C_Sql Into N_Can;
  End Loop;
End;
/
Elapsed: 00:00:01:93

-- Revisamos la cantidad de sentencias almacenadas en la librería SQL
Select Count(*) Cantidad From V$Sql
Where Sql_Text Like 'SELECT COUNT(*) FROM PERSONAS WHERE IDENTIFICACION=%';
  CANTIDAD
----------
         1
Elapsed: 00:00:00:01


Ahora analicemos como esta la memoria
Gráfica de uso de la memoria SHARED POOL

Vemos que ahora el tamaño disponible de la Shared Pool no se disminuyó tanto y de igual forma el Sql Area no aumento demasiado ya que solo se guardó una sentencia en la Sql Area aunque se hayan ejecutado 10,000 consultas con diferente identificación, lo que representa 1 Hard Parse y 9,999 Soft Parse (Esto es bueno para el Oracle Server). El tiempo de ejecución disminuyó a 1.93 segundos.

Conclusiones
Vemos que los mejores valores en resultados son con el parámetro de base de datos CURSOR_SHARING en SIMILAR para obtener mejores tiempos de respuesta, menos uso en MB de las Sql Library y dejando mas espacio disponible para la Shared Pool y reduciendo los Hard Parse.

Recomendaciones
Es cierto que este parámetro mejor los tiempo de respuesta, pero a que costo? el costo es que el motor de base de datos tiene mas trabajo para procesar cada sentencia.

Solo recomedaría cambiar el parámetro de forma temporal hasta que se logre modificar los programas para que usen variables bind, o en casos extremos, pero de ahi no lo recomedaría.

Este parámetro CURSOR_SHARING=SIMILAR  lo aplique en mi  base de datos Oracle  RAC de dos nodos montados en servidores WS2008 R2, 2 procesadores con 4 nucleos de 2.93 Ghz de y con 24GB de memoria Ram, pero la medicina fue peor que la enfermedad se presentaba error :
ORA-00600: internal error code, arguments: [kcblasm_1], [103], [], [], [], [], [], [].

Para este error en el metalink de Oracle recomendaba cambiar el parametro CURSOR_SHARING a EXACT.

Este error sólo se me presentó en Oracle RAC pero no en Oracle Single Instance, lo que me hace pensar que el parámetro CURSOR_SHARING=SIMILAR no funca para RAC.