mejora rendimiento

Colapsar
X
 
  • Tiempo
  • Mostrar
Limpiar Todo
nuevos mensajes
  • budista1
    Senior Member
    • sep
    • 154

    #1

    mejora rendimiento

    ¿Cómo mejoro rendimiento a estos 2 selects? (alternativas)

    SELECT * INTO TABLE it_ass_tipus
    FROM zef_ass_tipus
    WHERE retencio_irpf = 'X' AND
    tipus_ajust <> '/'.

    * Obtenim les dades de la sac
    SELECT * INTO TABLE it_sac
    FROM zef_sac FOR ALL ENTRIES IN it_ass_tipus
    WHERE bukrs = p_bukrs AND
    gjahr = p_gjahr AND
    id_tipus_ass = it_ass_tipus-tipus_complert AND
    belnr IN s_belnr AND
    tercer IN s_tercer AND
    estat IN s_estat AND
    estat <> '99' AND
    hkont IN s_hkont AND
    tercer IN r_terc.

    GRACIAS Y SALUDOS ABAPEROS
  • jtristan
    Senior Member
    • oct
    • 240

    #2
    Desconociendo el tamaño de las tablas así como los índices que estén creados podrías hacer un JOIN en vez de un FOR ALL ENTRIES. El for all entries sino recuerdo mal no deja de ser un UNION por cada registro de la tabla temporal.

    Sería algo así:
    SELECT * INTO TABLE table
    FROM zef_ass_tipus
    LEFT JOIN
    zef_sac
    ON
    zef_ass_tipus~tipus_complert = zef_sac~id_tipus_ass
    WHERE retencio_irpf = 'X' AND
    tipus_ajust <> '/' AND
    bukrs = p_bukrs AND
    gjahr = p_gjahr AND
    belnr IN s_belnr AND
    tercer IN s_tercer AND
    estat IN s_estat AND
    estat <> '99' AND
    hkont IN s_hkont AND
    tercer IN r_terc.


    Un saludo.

    Comentario

    • budista1
      Senior Member
      • sep
      • 154

      #3
      Muchas Gracias

      Gracias compañero!!

      voy a probarlo.

      La tabla ZEF_SAC tiene unos 300 mil registros, los campos clave son

      MANDT
      BUKRS
      GJAHR
      NUM_SAC

      La tabla ZEF_ASS_TIPUS solo unos 500 registros

      campos clave :
      MANDT
      TIPUS
      ESTAT


      Por qué transacción puedo evaluar el rendimiento?
      (a parte de la se30)

      Saludos!

      Comentario

      • Mari.Sole
        Senior Member
        • nov
        • 121

        #4
        Hola,
        Una simple acotación. Podrías probar de eliminar del SELECT la clausula <> eso hace que se pierda mucha performance en el acceso a la BD.
        Si eliminas esa cluasula luego de la selección de datos deberías agregar una rutina que al resultado obtenido de esa selección (almacenado en tabla interna) deberías recorrerla y eliminar los registros cuya condicion quitaste del SELECT.

        Saludos!

        Comentario

        • VLozano
          Senior Member
          • nov
          • 124

          #5
          Antes que nada:
          1. FOR ALL ENTRIES:
          si vas a usar la cláusula FOR ALL ENTRIES IN, asegúrate primero de que la tabla interna sobre la que se va a filtrar tiene datos.
          Código:
          SELECT fields 
            INTO TABLE it_tab1 
            FROM table 
            WHERE conditions.
          DESCRIBE TABLE it_tab1.
          IF sy-tfill > 0.
            SELECT fields2
              INTO TABLE it_tab2
              FROM table2
              FOR ALL ENTRIES IN it_tab1
              WHERE conditions2.
          ENDIF.
          En tu caso, si la primera SELECT no retorna datos, la segunda lee TODOS LOS REGISTROS DE LA TABLA. Y eso duele.

          2. SELECT *
          No es conveniente utilizar esta sentencia. Es mucho más rápido de escribir, pero a no ser que realmente necesites todos los datos de la tabla, estás metiéndole presión al servidor de datos (y al de aplicaciones).
          ------------------------------------------------------------------
          Y ahora una respuesta (que quizá no te guste)

          Alternativas al FOR ALL ENTRIES:
          - INNER JOIN
          - SELECT SINGLE en un LOOP

          La mayoría de desarrolladores "a la antigua" (entre los que me podrías incluir) te dirían que la última es un suicidio. No es cierto. La elección entre las tres posibilidades depende de la cantidad (y reparto entre tablas) de datos a leer, de si se utilizan los índices en las condiciones de selección, y de la carga de memoria que pueda tolerar tu servidor.

          Viendo las condiciones de la segunda SELECT, podríamos deducir que el campo que usas para filtrar en el FOR ALL ENTRIES no forma parte de la clave ni empieza un índice. Si es el caso, el INNER JOIN podría llegar a ser contraproducente.

          Si las cláusulas WHERE que has dado usan índices, y el rendimiento sigue siendo malo (¿seguro que el cuello de botella está ahí?), quizá deberías usar otra aproximación al problema. Por ejemplo, si realizas un tratamiento masivo en un LOOP posterior sobre la primera tabla, en el que realizas un READ TABLE para coger los datos de la segunda, quizá te interesaría intentar un SELECT-LOOP-SELECT. Mucha gente se llevaría ahora las manos a la cabeza, pero con los nuevos motores de BBDD y el rendimiento del que son capaces los servidores hoy en día, ese gesto está desfasado. Te lo dice un abuelete.
          Código:
          SELECT fields
            INTO TABLE t_tab1
            FROM tab1
            WHERE conditions.
          LOOP AT t_tab1 INTO w_tab1.
            REFRESH t_tab2.
            SELECT fields2
              INTO TABLE t_tab2
              FROM tab2
              WHERE conditions2. "añadiendo las condiciones sobre w_tab1
            LOOP AT t_tab2 INTO w_tab2.
          *    Trabajo
            ENDLOOP.
          ENDLOOP.
          "Porque algunos sabemos que somos parte del problema"
          - Pequeña guía para escribir mensajes en foros técnicos -

          Comentario

          • budista1
            Senior Member
            • sep
            • 154

            #6
            gracias pero..

            Antes de nada, muy agradecido por vuestra ayuda.

            Hice una 1a prueba cambiando unas selects por el join que me dijo un compañero de mundosap. De momento el rendimiento no ha mejorado :-(

            SELECT * INTO CORRESPONDING FIELDS OF TABLE it_sac
            FROM zef_sac
            LEFT JOIN
            zef_ass_tipus
            ON
            zef_sac~id_tipus_ass = zef_ass_tipus~tipus_complert
            WHERE
            * retencio_irpf = 'X'
            *AND
            *tipus_ajust <> '/' AND
            bukrs = p_bukrs AND
            gjahr = p_gjahr AND
            belnr IN s_belnr AND
            tercer IN s_tercer AND
            *estat IN s_estat AND
            *estat <> '99' AND
            hkont IN s_hkont AND
            tercer IN r_terc.

            Comentario

            • robert_milan
              Senior Member
              • jun
              • 315

              #7
              Yo lo que haria

              ¿Cómo mejoro rendimiento a estos 2 selects? (alternativas)
              * it_ass_tipus definela con campos que necesites *
              * it_sac definela con campos que necesites *
              SELECT [Pon los campos que necesites] INTO TABLE it_ass_tipus
              FROM zef_ass_tipus
              WHERE retencio_irpf = 'X' AND
              tipus_ajust <> '/'.
              If sy-subrc = 0.
              * Obtenim les dades de la sac
              SELECT [Pon los campos que necesites] INTO TABLE it_sac
              FROM zef_sac FOR ALL ENTRIES IN it_ass_tipus
              WHERE bukrs = p_bukrs AND
              gjahr = p_gjahr AND
              id_tipus_ass = it_ass_tipus-tipus_complert AND
              belnr IN s_belnr AND
              tercer IN s_tercer AND
              estat IN s_estat AND
              estat <> '99' AND
              hkont IN s_hkont AND
              tercer IN r_terc.

              A la tabla ZEF_SAC creale un indice con los campos que usas aqui.
              endif.

              Saludos
              Un Huevon No Inútil


              Solo di lo que piensas, a la mejor tienes la mejor respuesta....

              Si alguien ya lo hizo, copialo y cambiale las variables total es un codigo nuevo.....

              Si SAP lo hace se puede hacer, no me pidas hacer algo que SAP no ha hecho.....

              Consultor FI jr/ABAP Sr.

              Comentario

              • budista1
                Senior Member
                • sep
                • 154

                #8
                nueva idea

                Y si hago 2 selects normales, lo meto en 2 tablas internas y luego hago

                un loop de una tabla
                y read table binary search con la otra?

                Podría mejorar la cosa

                Comentario

                • VLozano
                  Senior Member
                  • nov
                  • 124

                  #9
                  Originalmente publicado por budista1
                  Y si hago 2 selects normales, lo meto en 2 tablas internas y luego hago

                  un loop de una tabla
                  y read table binary search con la otra?

                  Podría mejorar la cosa
                  Eso dependerá de algunos factores, como el número de registros de cada tabla (sobretodo de la segunda), la memoria del servidor, su configuración...

                  Yo antes que intentar eso haría pruebas de rendimiento con un SELECT-LOOP-SELECT, como te he comentado antes. Siempre estás a tiempo de echarte atrás, pero probablemente te sorprendas.
                  "Porque algunos sabemos que somos parte del problema"
                  - Pequeña guía para escribir mensajes en foros técnicos -

                  Comentario

                  Trabajando...