Analizar y probar el código
Uso correcto de tipos de datos y conversiones de tipos
Campos de caracteres de procesamiento
Uso de la transferencia de código en ABAP SQL
Mejora del rendimiento de la tabla interna
Implementar verificaciones de autorización
Diseño de código orientado a objetos efectivo
Definir y trabajar con clases de excepción
Añadir documentación al código ABAP

Trabajar con tablas Sorted y Hashed

Objective

After completing this lesson, you will be able to trabaje con tablas clasificadas y de claves de control.

Pruébelo: preparación de ejemplo de código

  1. Seleccione Ctrl + Mayús + N para crear un nuevo objeto de ABAP Repository.
  2. Escriba la base de datos de palabras en el campo de filtro, marque el resultado de la búsqueda Tabla de base de datos y seleccione Continuar.
  3. Asigne el nuevo objeto al paquete con el que está trabajando e introduzca el nombre ZS4D401_FLIGHTS. Introduzca una descripción para la tabla y seleccione Siguiente.
  4. Asigne el objeto a una orden de transporte y seleccione Finalizar.
  5. Introduzca el siguiente código entre llaves:
    Code Snippet
    1234567891011
    key client : abap.clnt not null; key carrier_id : /dmo/carrier_id not null; key connection_id : /dmo/connection_id not null; key flight_date : /dmo/flight_date not null; @Semantics.amount.currencyCode : 'zs4d401_flights.currency_code' price : /dmo/flight_price; currency_code : /dmo/currency_code; plane_type_id : /dmo/plane_type_id; seats_max : /dmo/plane_seats_max; seats_occupied : /dmo/plane_seats_occupied;
  6. Seleccione Ctrl + F3 para activar la tabla.
  7. Cree una nueva clase ABAP llamada ZCL_FILL_ZS4D401_FLIGHTS.
  8. Introduzca el siguiente código en la implementación del método main:
    Code Snippet
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
    DATA flights TYPE TABLE OF /dmo/flight. DATA insert_tab TYPE TABLE OF /dmo/flight. DELETE FROM ZS4D401_flights. SELECT FROM /dmo/flight FIELDS * ORDER BY carrier_Id, connection_id INTO TABLE @flights . LOOP AT flights INTO DATA(first_date). * Original table flights has 2 flights per connection. Only process the first IF sy-tabix MOD 2 = 0. CONTINUE. ENDIF. *Extend flight dates by 2000 days DO 2000 TIMES. APPEND first_date TO insert_tab. first_date-flight_date += 1. ENDDO. * ENDIF. ENDLOOP. * Read highest connection number for each flight SELECT FROM /dmo/flight AS main FIELDS carrier_Id, connection_id, flight_date, price, currency_code, plane_type_id WHERE connection_id = ( SELECT MAX( connection_id ) FROM /dmo/flight WHERE carrier_id = main~carrier_id ) AND flight_Date = ( SELECT MIN( flight_date ) FROM /dmo/flight WHERE carrier_id = main~carrier_id AND connection_id = main~connection_id ) GROUP BY carrier_id, connection_Id, flight_date, price, currency_code, plane_type_id ORDER BY carrier_id, connection_id INTO TABLE @DATA(max). *Add 50 new connection numbers and 2000 days of flights for each LOOP AT max INTO DATA(line). DO 50 TIMES. line-connection_id += 1. line-plane_type_id = SWITCH #( CONV i( line-connection_id ) MOD 2 WHEN 0 THEN 'A330' WHEN 1 THEN 'A350' ). first_date = CORRESPONDING #( line ). DATA(repetitions) = COND i( WHEN line-carrier_id = 'LH' AND line-connection_id = '0405' THEN 4000 ELSE 2000 ). DO repetitions TIMES. first_date-seats_max = 220. APPEND first_date TO insert_tab. first_date-flight_date += 1. ENDDO. ENDDO. ENDLOOP. SORT insert_tab BY carrier_Id connection_id flight_date. DELETE ADJACENT DUPLICATES FROM insert_tab COMPARING carrier_id connection_id flight_date. INSERT ZS4D401_flights FROM TABLE @insert_tab. out->write( |Generated { sy-dbcnt } rows in table ZS4D401_flights| ).
  9. Seleccione Ctrl + F3 para activar la clase.
  10. Seleccione F9 para ejecutar la clase. El método main rellena una tabla de base de datos adicional necesaria para los fragmentos de código en las dos secciones siguientes.

Tablas Sorted y Hashed

Hasta ahora, hemos trabajado con tablas internas estándar. Los datos de una tabla estándar no se mantienen en un orden de clasificación determinado. Por lo tanto, cuando lee datos de la tabla, el sistema debe buscar la tabla secuencialmente hasta que encuentre la fila o filas que necesita. En función del tamaño de la tabla, esto puede tardar un poco.

Puede optimizar el rendimiento de los accesos de lectura a tablas internas mediante tablas clasificadas o de claves de control.

En una tabla clasificada, el contenido de la tabla siempre se clasifica según los campos clave en orden ascendente. Cuando inserta un nuevo registro en la tabla, el sistema se asegura de que se coloca en la posición correcta. Puesto que los datos se clasifican siempre, el sistema puede recuperar registros de manera más eficiente que a partir de una tabla estándar (mientras se sigan unas reglas determinadas).

Las tablas hashed se gestionan mediante un algoritmo de control. De esta forma, se garantiza que el sistema pueda recuperar registros con rapidez aunque la tabla sea muy grande. Sin embargo, este aumento del rendimiento solo funciona en casos muy concretos.

Acceso a una tabla ordenada

En este vídeo verá cómo acceder a una tabla clasificada.

Cuando declara una tabla de claves de control, debe definirla con una clave única; nunca se permiten duplicados.

Vea el vídeo para saber cómo acceder a una tabla de claves de control.

Cuándo utilizar tablas estándar, clasificadas y de claves de control

Si rellena una tabla interna y posteriormente implementa un loop en toda la tabla, puede utilizar una tabla estándar. La optimización del rendimiento de las tablas Sorted y Hashed es irrelevante, ya que no hay ningún filtro en el loop.

Este ejemplo muestra cuándo debe utilizar tablas clasificadas y de claves de control. Contiene un loop sobre las conexiones de tabla utilizando el primer campo clave de la cláusula where. Este es un caso para utilizar una tabla clasificada, ya que el sistema puede utilizar la técnica de búsqueda binaria aunque la clave no se haya especificado completamente.

Dentro del loop, el programa busca entradas en la tabla Compañías aéreas. Por lo tanto, hay accesos repetidos a la tabla utilizando la clave completa. Este es un caso ideal para utilizar una tabla de claves de control.

Tiempos de ejecución comparativos de tablas estándar, clasificadas y de claves de control

Esta figura compara los tiempos de ejecución de las tablas estándar, clasificadas y de claves de control.

Rellenar tablas clasificadas y de claves de control

Cuando utiliza una tabla estándar, puede utilizar la sentencia APPEND para añadir el contenido de un área de trabajo al final de la tabla. Esto no es posible con tablas de claves de control y provoca un error de sintaxis.

Técnicamente, puede utilizar la sentencia APPEND para rellenar una tabla clasificada. Sin embargo, corre el riesgo de provocar un error en tiempo de ejecución si la línea que intenta añadir no pertenece al final de la tabla según el orden de clasificación. Esto ocurriría en nuestro ejemplo.

La forma de rellenar una tabla de claves de control y rellenar una tabla clasificada de forma segura es utilizar la sentencia INSERT. INSERT garantiza que la nueva fila se inserte en la posición correcta de la tabla.

Pruébelo: tablas clasificadas y de claves de control

  1. Cree una clase nueva que implemente la interfaz IF_OO_ADT_CLASSRUN.
  2. Copie el siguiente fragmento de código en la parte de implementación del método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011
    * Run this class using the ABAP Profiler to measure relative access times for standard, sorted, and hashed tables data(flights) = new lcl_flights( ). flights->access_standard( ). flights->access_sorted( ). flights->access_hashed( ). out->write( |Done| ).
  3. Cambie a la pestaña Tipos locales y copie el siguiente fragmento de código en el editor:
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
    CLASS lcl_flights DEFINITION. PUBLIC SECTION. METHODS constructor. METHODS access_standard. METHODS access_sorted. METHODS access_hashed. PRIVATE SECTION. DATA standard_table TYPE STANDARD TABLE OF zs4d401_flights WITH NON-UNIQUE KEY carrier_id connection_id flight_date. DATA sorted_table TYPE SORTED TABLE OF zs4d401_flights WITH NON-UNIQUE KEY carrier_id connection_id flight_date. DATA hashed_table TYPE HASHED TABLE OF zs4d401_flights WITH UNIQUE KEY carrier_id connection_id flight_date. DATA key_carrier_id TYPE /dmo/carrier_id. DATA key_connection_id TYPE /dmo/connection_id. DATA key_date TYPE /dmo/flight_date. METHODS set_line_to_read. ENDCLASS. CLASS lcl_flights IMPLEMENTATION. METHOD access_hashed. DATA(result) = hashed_table[ carrier_Id = me->key_carrier_id connection_Id = me->key_connection_id flight_date = me->key_date ]. ENDMETHOD. METHOD access_sorted. DATA(result) = sorted_table[ carrier_Id = me->key_carrier_id connection_Id = me->key_connection_id flight_date = me->key_date ]. ENDMETHOD. METHOD constructor. SELECT FROM zs4d401_flights FIELDS * INTO TABLE @standard_table. SELECT FROM zs4d401_flights FIELDS * INTO TABLE @sorted_table. SELECT FROM zs4d401_flights FIELDS * INTO TABLE @hashed_table. set_line_to_read( ). ENDMETHOD. METHOD access_standard. DATA(result) = standard_table[ carrier_Id = me->key_carrier_id connection_Id = me->key_connection_id flight_date = me->key_date ]. ENDMETHOD. METHOD set_line_to_read. DATA(line) = standard_table[ CONV i( lines( standard_table ) * '0.65' ) ]. me->key_carrier_id = line-carrier_Id. me->key_connection_Id = line-connection_id. me->key_date = line-flight_date. ENDMETHOD. ENDCLASS.
  4. Seleccione Ctrl + F3 para activar la clase.
  5. Haga clic con el botón derecho en el Editor y seleccione Perfil como...Aplicación ABAP (consola).
  6. En Detalles, desmarque la casilla de selección Acceso a base de datos SQL y seleccione Finalizar.
  7. Cambie a la perspectiva ABAP Profiler y haga doble clic en el elemento trace (es posible que primero deba actualizar la visualización).
  8. Seleccione Lista de aciertos.
  9. Compare los tiempos de ejecución de los métodos access_standard( ), access_sorted( ) y access_hashed( ).

Trabajar con tablas Sorted y Hashed

Se da cuenta de que su código contiene grandes tablas internas del tipo Tabla estándar. Analice la forma en que se accede a estas tablas en el código y compruebe que solo se accede a ellas mediante clave. Para mejorar el rendimiento, modifique la definición de las tablas internas a Tabla clasificada o Tabla de claves de control, en función de la forma en que se acceda a ellas.

Modelo:

  • /LRN/CL_S4D401_ITS_FSYM (clase global)

Solución:

  • /LRN/CL_S4D401_ITS_TABLE_KIND (clase global)

Tarea 1: Copiar plantilla (opcional)

Copie la clase de modelo /LRN/CL_S4D401_ITS_FSYM. Si ha finalizado el ejercicio anterior, puede omitir esta tarea y continuar editando su clase ZCL_##_SOLUTION.

Pasos

  1. Copie la clase /LRN/CL_S4D401_ITS_FSYM en una clase de su propio paquete (nombre sugerido: ZCL_##_SOLUTION, donde ## representa su número de grupo).

    1. En el Explorador de proyectos, haga clic con el botón derecho en la clase /LRN/CL_S4D401_ITS_FSYM para abrir el menú contextual.

    2. En el menú contextual, seleccione Duplicar....

    3. Introduzca el nombre del paquete en el campo Paquete. En el campo Nombre, introduzca ZCL_##_SOLUTION, donde ## representa su número de grupo.

    4. Seleccione Siguiente.

    5. Confirme la orden de transporte y seleccione Finalizar.

  2. Active la copia.

    1. Pulse Ctrl + F3 para activar la clase.

Tarea 2: Ajustar CONNECTIONS_BUFFER

Utilice la referencia de utilización para el atributo estático connections_buffer de la clase local LCL_PASSENGER_FLIGHT. Modifique la definición de connections_buffer para que se adapte mejor a la forma en que se accede a ella.

Pasos

  1. Navegue a la definición del atributo estático connections_buffer en la clase local LCL_PASSENGER_FLIGHT.

    1. Por ejemplo, expanda el nodo LCL_PASSENGER_FLIGHT en la vista Esquema y seleccione CONNECTIONS_BUFFER.

  2. Cree la referencia de utilización para el atributo connections_buffer.

    1. En la sentencia CLASS-DATA, haga clic con el botón derecho en connections_buffer y seleccione Obtener referencia de utilización. Como alternativa, puede colocar el cursor en connections_buffer y pulsar Ctrl + Mayús + G.

    2. Analice la lista en la vista Buscar debajo del editor. Coloque el cursor sobre un hallazgo para visualizar el enunciado completo.

  3. Ajuste la definición del atributo connections_buffer. Seleccione la clase de tabla y la definición de clave que mejor se adapte al acceso de lectura.

    1. Modifique la clase de tabla a HASHED TABLE.

    2. Modifique la definición de clave a una clave unívoca con carrier_id y connection_id como campos clave.

    3. Ajuste el código de la siguiente manera:

      ABAP
      1234
      * CLASS-DATA connections_buffer TYPE TABLE OF st_connections_buffer. CLASS-DATA connections_buffer TYPE HASHED TABLE OF st_connections_buffer WITH UNIQUE KEY carrier_id connection_id.

Tarea 3: Ajustar FLIGHTS_BUFFER

Utilice la referencia de utilización para el atributo estático flights_buffer de la clase local LCL_PASSENGER_FLIGHT. Modifique la definición de flights_buffer para que se adapte mejor a la forma en que se accede al atributo.

Pasos

  1. Navegue a la definición del atributo estático flights_buffer en la clase local LCL_PASSENGER_FLIGHT.

    1. Por ejemplo, expanda el nodo LCL_PASSENGER_FLIGHT en la vista Esquema y seleccione FLIGHTS_BUFFER.

  2. Cree la referencia de utilización para el atributo flights_buffer.

    1. En la sentencia CLASS-DATA, haga clic con el botón derecho en flights_buffer y seleccione Obtener referencia de utilización. Como alternativa, puede colocar el cursor en flights_buffer y pulsar Ctrl + Mayús + G.

    2. Analice la lista en la vista Buscar debajo del editor. Coloque el cursor sobre un hallazgo para visualizar el enunciado completo.

  3. Ajuste la definición del atributo flights_buffer. Seleccione la clase de tabla y la definición de clave que mejor se adapten a los accesos de lectura.

    1. Modifique la clase de tabla a SORTED TABLE.

    2. Modifique la definición de clave a una clave no unívoca con carrier_id, connection_id y flight_date como campos clave.

    3. Ajuste el código de la siguiente manera:

      ABAP
      1234
      * CLASS-DATA: flights_buffer TYPE TABLE OF st_flights_buffer. CLASS-DATA: flights_buffer TYPE SORTED TABLE OF st_flights_buffer WITH NON-UNIQUE KEY carrier_id connection_id flight_date.
  4. Analice los errores de sintaxis en la vista Problemas.

    1. Analice la vista Problemas debajo del editor.

  5. Elimine o comente la sentencia SORT redundante.

    1. Ajuste el código de la siguiente manera:

      ABAP
      1
      * SORT flights_buffer BY carrier_id connection_id flight_date.
  6. Active y pruebe su clase global como aplicación de consola.

    1. Pulse Ctrl + F3.

    2. Pulse F9.

Tarea 4: Cuantificar la mejora

Utilice ABAP Profiling para cuantificar la mejora del rendimiento lograda ajustando el tipo de las dos tablas internas.

Pasos

  1. Localice la clase de modelo /LRN/CL_S4D401_ITS_FSYM en el explorador de proyectos.

  2. Defina el perfil de la clase de modelo /LRN/CL_S4D401_ITS_FSYM como una aplicación de consola ABAP.

    1. Haga clic con el botón derecho en la clase de modelo /LRN/CL_S4D401_ITS_FSYM en el Explorador de proyectos y seleccione Perfil Comoaplicación ABAP (consola).

    2. Seleccione Finalizar.

    3. Espere hasta que aparezca la vista Consola o se actualice.

  3. Vuelva a su propia clase (ZCL_##_SOLUTION, donde ## es su número de grupo) y fíltrela de la misma manera.

    1. Localice su propia clase en el Explorador de proyectos.

    2. Haga clic con el botón derecho en su clase en el Explorador de proyectos y seleccione Perfil Comoaplicación ABAP (consola).

    3. Espere hasta que aparezca la vista Consola o se actualice.

  4. Cambie a la perspectiva ABAP Profiling y compare los dos traces ABAP.

    1. Para abrir la perspectiva ABAP Profiling, seleccione VentanaPerspectivaAbrir perspectivaOtros....del menú de eclipse. A continuación, seleccione Generación de perfiles ABAP y Abrir. (Como alternativa, si está disponible, puede seleccionar el icono Generación de perfiles ABAP en la esquina superior derecha de la barra de herramientas de eclipse).

    2. En la vista Traces ABAP en la parte inferior, despliegue el nodo que corresponde a su proyecto en la nube ABAP.

    3. Pulse F5 para actualizar la lista de resultados de trace. Los dos primeros resultados de trace deben nombrarse como su propia clase ABAP y la clase de modelo.

    4. Compare los valores de la columna Tiempo de ejecución (s).

  5. Después del análisis, vuelva a la perspectiva ABAP.

    1. Cambie la perspectiva como lo ha hecho antes.