Desarrollando en Cobol y Natural sobre Plataforma Mainframe

viernes, 25 de marzo de 2016

Computadoras de alto rendimiento



lunes, 21 de marzo de 2016

Query SQL con UNION y con UNION ALL (1)

En muchas ocasiones, tras implementar un determinado código SQL, nos damos cuenta de que su rendimiento a la hora de ejecutarse es bastante deficiente. Una forma de optimizar los tiempos de ejecución es recurrir a la cláusula UNION e incorporarla a nuestras queries siempre que sea posible. En este sentido, disponemos de dos variantes principales para codificar este comando: UNION ALL y UNION.

Rendimiento de Query SQL con UNION


La instrucción UNION nos va a permitir integrar las extracciones realizadas por dos queries distintas. Si prescindimos de la cláusula UNION, lo más normal es que, en vez de unir dos queries sencillas, tengamos que recurrir a una query única de complejidad mucho mayor. Y, lo que es peor, el rendimiento de esta query compleja probablemente será muy inferior a la solución con UNION.

Por lo general (lo he podido comprobar en mi propia experiencia), una declaración SQL mediante UNION suele tener tiempos de ejecución mucho mejores que la misma extracción pero realizada mediante una query única más compleja (que integre la funcionalidad de las queries sencillas empleadas en dicho UNION). Esto lo he verificado con el uso del comando EXPLAIN, así que no merece la pena complicarse la vida.


Para ver cómo funcionaría la instrucción UNION vamos a ver un ejemplo en el que inicialmente no se ha empleado esta instrucción para mejorar el rendimiento del código.

  SELECT *                                                     
  FROM JJDB22.JJETRAT0 A, JJDB22.JJTRAMT0 B
  WHERE                                                        
    ((A.JJTU_CO_INTERN = 'Z.BR' AND A.JJCA_CO_INTERN = 1)

    OR (A.JJTU_CO_INTERN_1 = 'Z.BR' AND A.JJCA_CO_INTERN_1 = 1))

    AND A.JJTU_CO_INTERN   = B.JJTU_CO_INTERN                  
    AND A.JJCA_CO_INTERN   = B.JJCA_CO_INTERN                  
    AND A.JJTU_CO_INTERN_1 = B.JJTU_CO_INTERN_1  
    AND A.JJCA_CO_INTERN_1 = B.JJCA_CO_INTERN_1  
    AND A.JJAM_NU_INTERN   = B.JJAM_NU_INTERN       


Aparentemente, esta query tiene un aspecto muy compacto y parece bien codificada pero, por desgracia, sus tiempos de ejecución eran superiores a 100 milisegundos. Por tanto, no hubo más remedio que pensar en formas de mejorar su rendimiento. Y aquí es donde entra en juego la cláusula UNION.

¿Cómo codificar una Query SQL con UNION?


Una vez vista la query compleja, vamos a examinar cómo se podría mejorar el rendimiento de la misma mediante UNION. Para ello, lo que tendríamos que determinar es cómo se podría dividir la query inicial en varias subqueries más sencillas, de manera que posteriormente podamos unir estas subextracciones mediante la cláusula UNION.

En el ejemplo que nos ocupa, vemos que se está usando el operador OR en la cláusula WHERE. Por tanto, aquí lo más fácil sería dividir la query total en dos queries más pequeñas, de manera que cada una de ellas extraiga el contenido de cada operando del OR. Obviamente, estas subqueries tendrán tiempos de ejecución muy bajos, ya que su código será mucho más sencillo.


Dicho y hecho. Haciendo la división, estas serían las dos declaraciones que nos quedarían para las nuevas queries. La primera parte del OR sería la siguiente.

  SELECT *                                                     
  FROM JJDB22.JJETRAT0 A, JJDB22.JJTRAMT0 B
  WHERE                                                        
     ( A.JJTU_CO_INTERN = 'Z.BR' AND A.JJCA_CO_INTERN = 1)

    AND A.JJTU_CO_INTERN   = B.JJTU_CO_INTERN                  
    AND A.JJCA_CO_INTERN   = B.JJCA_CO_INTERN                   
    AND A.JJAM_NU_INTERN   = B.JJAM_NU_INTERN  
  


Y la segunda parte del OR sería esta.

  SELECT *                                                     
  FROM JJDB22.JJETRAT0 A, JJDB22.JJTRAMT0 B
  WHERE                                                        
     (A.JJTU_CO_INTERN_1 = 'Z.BR' AND A.JJCA_CO_INTERN_1 = 1)
                  
    AND A.JJTU_CO_INTERN_1 = B.JJTU_CO_INTERN_1  
    AND A.JJCA_CO_INTERN_1 = B.JJCA_CO_INTERN_1  
    AND A.JJAM_NU_INTERN   = B.JJAM_NU_INTERN  
 
  

Y ahora viene la parte que verdaderamente nos interesa. Una vez que hemos dividido la query padre en queries hijas más pequeñas, llega el momento de dar entrada a UNION. ¿Y cómo se utiliza esta cláusula en una query? Pues muy sencillo, simplemente hay que insertar la instrucción UNION entre las dos queries hijas del siguiente modo.

  SELECT *                                                     
  FROM JJDB22.JJETRAT0 A, JJDB22.JJTRAMT0 B
  WHERE                                                        
     ( A.JJTU_CO_INTERN = 'Z.BR' AND A.JJCA_CO_INTERN = 1)

    AND A.JJTU_CO_INTERN   = B.JJTU_CO_INTERN                  
    AND A.JJCA_CO_INTERN   = B.JJCA_CO_INTERN                   
    AND A.JJAM_NU_INTERN   = B.JJAM_NU_INTERN  


  UNION

  SELECT *                                                     
  FROM JJDB22.JJETRAT0 A, JJDB22.JJTRAMT0 B
  WHERE                                                        
     (A.JJTU_CO_INTERN_1 = 'Z.BR' AND A.JJCA_CO_INTERN_1 = 1)
                  
    AND A.JJTU_CO_INTERN_1 = B.JJTU_CO_INTERN_1  
    AND A.JJCA_CO_INTERN_1 = B.JJCA_CO_INTERN_1  
    AND A.JJAM_NU_INTERN   = B.JJAM_NU_INTERN  
 
 

El listado extraído por el UNION anterior es idéntico al que hubiésemos obtenido mediante la ejecución de la query inicial más compleja. La única diferencia es que, mediante el uso del UNION, hemos conseguido que su tiempo de ejecución caiga por debajo de los 100 milisegundos y, por tanto, que ya tengamos entre nuestras manos un código adecuado para entregar al cliente.

-------------------------------------------------------------------------------------------------------------------------------
Tip: Aquí te explico cómo almacenar queries en QMF y también cómo recuperar queries en QMF.
-------------------------------------------------------------------------------------------------------------------------------



Hasta aquí todo lo que teníamos que ver sobre la implementación de una query con UNION. El próximo día, en un nuevo post, trataremos de revisar el funcionamiento de la cláusula UNION ALL en una sentencia SQL. Hay ciertas diferencias entre ambas instrucciones y es importante que las tengamos en cuenta a la hora de desarrollar los accesos a DB2 en nuestros programas Cobol.

Pues nada, eso es todo por hoy. Como siempre, quedáis citados a la segunda parte del post, donde completaremos la visión global de UNION y de UNION ALL. Espero (y deseo) que lo comentado os sea de la máxima utilidad...

Saludos.

lunes, 14 de marzo de 2016

Transacción CMAC: Mensajes de error CICS

La transacción CMAC de CICS es una herramienta muy sencilla, pero que nos va a permitir acceder a una explicación detallada del error CICS que nos esté bloqueando el avance en un momento dado. Aunque su uso no supone complejidad alguna, a mi siempre me gusta incluirla en la lista de transacciones básicas CICS, fundamentalmente debido a su gran utilidad. Estoy seguro de que a vosotros también os gustará disponer de esta ayuda en vuestra instalación.

Transacción CMAC: Mensajes de error


En líneas generales, podemos decir que la transacción CMAC nos permite introducir un determinado código de error y, a partir de él, nos va a devolver una explicación del mensaje de error. También nos proporcionará algunas directrices de cómo podríamos proceder para tratar de subsanar el problema con el que nos hemos encontrado. Se trata, por tanto, de una base de datos de errores CICS.

A continuación, vamos a enumerar los pasos necesarios para poder recuperar la información mencionada. Son los siguientes.

1º) En primer lugar, procedemos a entrar en la sesión CICS y, una vez dentro, introducimos la transacción CMAC.



2º) Tras pulsar INTRO, se nos desplegará la ventana inicial de la herramienta, en donde aparecen dos campos pendientes de provisionar: COMPONENT ID y MESSAGE NUMBER.







En el campo COMPONENT ID tendremos que indicar la tipología del error y en MESSAGE NUMBER habrá que especificar el código numérico del mensaje de error o aviso para el que queremos conocer más detalles. Por ejemplo, en la imagen anterior hemos introducido "TC" y "1060" (correspondientes al error CICS DFHTC1060).

3º) Si insertamos COMPONENT ID y MESSAGE NUMBER y, a continuación, pulsamos INTRO, la aplicación nos llevará a la ventana de detalle del mensaje.



En el ejemplo podemos ver que en dicha ventana se muestra el título DFHTC1060 APPLID INSUFFICIENT STORAGE - CODE(X'CODE') IN MODULE DFHTCRP. En el informe nos aparecen varios apartados (EXPLANATION, SYSTEM ACTION, USER RESPONSE, DESTINATION, MODULE y MESSAGE INSERTS) en los que se nos va explicando detalladamente en qué consiste el error y cuáles son las medidas que podemos tomar para tratar de subsanarlo.








   

Conclusiones sobre la Transacción CMAC


Y no hay mucho más que comentar acerca de esta transacción. Se trata de una herramienta de uso sencillo y con un objetivo muy definido. Eso sí, las explicaciones de los errores son detalladas y útiles. En más de una ocasión os puede dar buenas ideas acerca de cómo superar ese error CICS que os está impidiendo avanzar tanto con el desarrollo de vuestros módulos Cobol como con la implementación de las fases JCL.

Eso sí, verificad que en vuestra instalación está disponible. He comprobado que algunas empresas se olvidan de instalar CMAC y, entonces, no podréis acceder a esta ayuda en vuestro día a día. Si tenéis la posibilidad, pedidle a vuestro cliente que lo instale en el entorno.

Como he dicho al principio, aunque en muchos listados no aparezca, yo siempre incluyo a CMAC entre las transacciones básicas de CICS. Ya sé que es una transacción muy sencilla, pero el hecho de que una herramienta sea simple no significa que no sea importante para nuestro desempeño. Ya lo iréis comprobando con el tiempo.

Y eso es todo por lo que respecta a CMAC. Supongo que os habrá quedado bastante claro el funcionamiento de la transacción pero, si no es así, no dudéis en dejarme los comentarios que creáis convenientes...

Saludos.

lunes, 7 de marzo de 2016

EXPLAIN con CA SQL-Ease for DB2 for ZOS (y 2)

Hace algunas semanas estuvimos viendo cómo se podía lanzar un chequeo EXPLAIN sobre una sentencia SQL de un programa Cobol. Esta función nos permitía obtener un informe (ACCESS PATH ANALYSIS) en el que se nos mostraba información acerca de las tablas DB2 utilizadas en nuestro objeto. Lo más importante es que se nos indicaba el coste, en milisegundos, que iba a requerir la ejecución de las instrucciones SQL.

En la primera parte del presente artículo estuvimos viendo cómo lanzar un EXPLAIN desde el editor de nuestro programa Cobol (ver post EXPLAIN con CA SQL-Ease for DB2 for ZOS - 1). Hoy veremos cómo se podría lanzar este mismo chequeo EXPLAIN desde el informe ACCESS PATH ANALYSIS. De esta forma, ahorraremos tiempo a la hora de analizar el rendimiento de nuestro programa, ya que no tendremos que estar cambiando entre el editor del objeto y la herramienta CA SQL-Ease for DB2 for ZOS.

Lanzar EXPLAIN desde ACCESS PATH ANALYSIS


Con lo examinado en el anterior post ya podemos dar por vistos los pasos que tenemos que seguir para ejecutar un EXPLAIN en la herramienta CA SQL-Ease for DB2 for ZOS. Ahora os comentaré otra funcionalidad interesante que podemos encontrar en esta aplicación.

1º) Una vez estamos en el informe ACCESS PATH ANALYSIS, podemos irnos al final del todo escribiendo 'M' en la línea de comandos y pulsando PF8. Así nos aparecerá en pantalla el código de la query para la se ha ejecutado el informe EXPLAIN.




Lo bueno es que en esta misma pantalla podremos proceder a modificar la query como deseemos. Esto nos permitirá probar diversas alternativas para optimizar el código y nos facilitará la realización del trabajo necesario para rebajar el coste por debajo de los 100 milisegundos.

2º) Una vez que hayamos terminado las modificaciones necesarias, podremos obtener de nuevo fácilmente el informe ACCESS PATH ANALYSIS para la query optimizada. Para ello, simplemente tendremos que introducir la instrucción EXPLAIN en la línea de comandos.







Tras pulsar INTRO se nos volverá a mostrar el informe EXPLAIN pero esta vez con los datos de Coste actualizados según las nuevas modificaciones que hayamos introducido en la query. Y lo mejor de todo es que podremos repetir este proceso tantas veces como necesitemos hasta que estemos totalmente seguros de que nuestro código no va a superar los 100 milisegundos de ejecución.

Conclusiones acerca de CA SQL-Ease for DB2 for ZOS


Hay ocasiones en las que implementamos un determinado código SQL y, cuando realizamos las pruebas en ejecución, nos damos cuenta de que el rendimiento del nuevo programa es muy inferior al esperado. Y lo peor es que, en muchos casos, es complicado determinar cuál es la query que está provocando el cuello de botella en la aplicación, sobre todo cuando trabajamos con código que contiene subqueries anidadas.

Para estos casos nos va a venir muy el empleo de la herramienta CA SQL-Ease for DB2 for ZOS. En particular, la opción 2 de la misma (EXPLAIN SQL) nos resultará muy útil para evaluar el rendimiento de las implementaciones SQL. Y, por supuesto, esto repercutirá en el rendimiento global de nuestros programas Cobol.

El lanzamiento del EXPLAIN nos proporcionará un informe ACCESS PATH ANALYSIS correspondiente a la query que hayamos seleccionado. Entre los resultados de dicho informe nos encontraremos el de Coste (en milisegundos), dato que nos resultará muy útil a la hora de verificar que nuestro código tiene un rendimiento aceptable.


Llegados a este punto, ahora ya es decisión vuestra incorporar esta función a vuestro catálogo de herramientas Cobol. Por mi parte, yo hace tiempo que la uso y nunca entregaría un programa al cliente sin comprobar que sus accesos SQL son óptimos. Creedme cuando os digo que esto, a largo plazo, será beneficioso para vosotros.

Pues nada, eso es todo lo que quería comentaros con respecto a CA SQL-Ease for DB2 for ZOS. Si tenéis la suerte de disponer de esta aplicación en vuestra instalación, no dudéis en utilizarla. Cualquier duda, ya sabéis que podéis dejarla aquí debajo.

Saludos.

Related Posts Plugin for WordPress, Blogger...