"
Apoiado por

Com muitos campos evita INTO CORRESPONDING FIELDS

Já avisei aqui que, em tabelas com muitos campos, é sempre de evitar fazer SELECT *, devendo-se sempre seleccionar explicitamente apenas os campos necessários.

Mas não avisei ainda que há ainda outra optimização que merece ser feita: evitar o INTO CORRESPONDING FIELDS OF TABLE.

Fiz as seguintes experiências com a tabela BSAD:

  1. Seleccionar a tabela inteirinha para uma tabela interna com a mesma estrutura;
  2. Seleccionar apenas 4 campos para uma tabela interna com a estrutura da BSAD usando INTO CORRESPONDING FIELDS;
  3. Seleccionar apenas 4 campos da tabela BSAD para uma tabela interna com apenas esses 4 campos ainda assim usando INTO CORRESPONDING FIELDS;
  4. Seleccionar apenas 4 campos da tabela BSAD

Eis os resultados:

  Duração % x
1 54.12s 100%  
2 3.40s 6.3% 16x
3 0.74s 1.4% 71x
4 0.70s 1.3% 77x

Traduzindo a coisa para miúdos:

  1. Tragédia. Evita a todo o custo. Mas isto já nós sabíamos;
  2. Seleccionando os campos demora apenas 6.3%, ou seja, é quase 16x mais rápido do que a abordagem javarda e preguiçosa;
  3. Enviando os campos para uma estrutura pequena em vez de para a estrutura grande demora apenas 1.4%. É 71x mais rápido do que a abordagem trágica e 4.5x mais rápido do que a que já tínhamos aconselhado;
  4. Evitando o uso do INTO CORRESPONDING quando a estrutura já é pequena ainda se ganha ligeiramente, mas nada de muito significativo.

Foste avisado.

Nota que a vantagem do uso do INTO CORRESPONDING FIELDS é introduzir alguma segurança pois mapeia os campos automaticamente. Caso este comando não seja usado é necessário garantir que os campos da estrutura destino estão todos lá e pela mesma ordem em que aparecem no SELECT.

Fica aqui o programa usado para obter estes resultados:


REPORT zzt_into_corresponding.

TYPES: BEGIN OF ty_campos,
         bukrs TYPE bukrs,
         belnr TYPE belnr_d,
         gjahr TYPE gjahr,
         buzei TYPE buzei,
       END OF ty_campos.

DATA: t_bsad_todos  TYPE STANDARD TABLE OF bsad,
      t_bsad_poucos type STANDARD TABLE OF bsad,
      t_campos      TYPE STANDARD TABLE OF ty_campos,
      rtime0        TYPE i,
      rtime1        TYPE i,
      rtime2        TYPE i,
      rtime3        type i,
      rtime4        type i.

GET RUN TIME FIELD rtime0.

SELECT * FROM bsad 
  INTO CORRESPONDING FIELDS OF TABLE t_bsad_todos.
GET RUN TIME FIELD rtime1.

SELECT bukrs belnr gjahr buzei FROM bsad 
  INTO CORRESPONDING FIELDS OF TABLE t_bsad_poucos.
GET RUN TIME FIELD rtime2.

SELECT bukrs belnr gjahr buzei FROM bsad 
  INTO CORRESPONDING FIELDS OF TABLE t_campos.
GET RUN TIME FIELD rtime3.

SELECT bukrs belnr gjahr buzei FROM bsad 
  INTO TABLE t_campos.
GET RUN TIME FIELD rtime4.

rtime0 = rtime1 - rtime0.
rtime1 = rtime2 - rtime1.
rtime2 = rtime3 - rtime2.
rtime3 = rtime4 - rtime3.

WRITE: / 'SELECT *', 50 rtime0,
       / 'SELECT campos INTO CORRESPONDING', 50 rtime1,
       / 'SELECT campos INTO CORRESPONDING estrutura', 50 rtime2,
       / 'SELECT campos INTO estrutura', 50 rtime3.

Para os mais picuinhas, é certo que para obter valores mais precisos seria necessário correr isto várias vezes e variar a ordem para obter médias e contornar caches. Mas as diferenças são tão gritantes que não restasm grandes dúvidas. Além disso experimentei inverter a ordem dos SELECTs e as proporções mantiveram-se.

Obrigado Sérgio Fraga pela dica.

Obrigado a metalkpirate1day pela foto.

O Abapinho saúda-vos.

4 comentários a “Com muitos campos evita INTO CORRESPONDING FIELDS”

  1. Custodio Diz:

    Ola Nuno,

    Ando meio sumido do seu blog, e quando apareco para discordar de ti. Veja esse blog post na SCN, feito pelo Thomas Zloch: http://scn.sap.com/docs/DOC-33976

    Abraco
    Custodio

  2. Nuno Godinho Diz:

    Olá Custodio, realmente é intringante. Obrigado por me mostrares isto. Vou ter de comparar os meus exemplos com os exemplos por ele apresentados. Porque os meus exemplos realmente mostram que o MOVE-CORRESPONDING é mais lento. Deve depender das situações.

  3. Giancarlo Fernandes Diz:

    Ola,

    Na minha humilde opinião, esse código não é válido para comparação de tempos de execução, da forma como foi proposto.

    Sempre que fazemos o PRIMEIRO acesso a uma informação qualquer no banco de dados, esta SEMPRE levará mais tempo do que os demais acessos à mesma informação, isto se deve pelo fato de no primeiro acesso não existir dados em cache no servidor de banco de dados.

    Se voce repetir 2 vezes o mesmo “SELECT *” nesse seu exemplo, vai notar que na segunda vez ele irá rodar extremamente mais rápido que na primeira vez, pois nesta segunda vez, como o servidor de banco de dados já fez cache em memória RAM, ele não irá ler dados fisicamente no disco rígido (que é lento), ao invés disso, ele vai ler diretamente do cache em memória RAM (que é muito mais rápido).

    Faça o teste no seu código, adicione uma variável “rtime5” e repita o “SELECT *” logo após o primeiro “SELECT *” e veja os tempos de execução.

    Abraço,
    Gian

  4. Nuno Godinho Diz:

    Olá Giancarlo,

    De facto, tens toda a razão. O teste é muito pouco científico :) Ainda assim, experimentei inverter a ordem dos SELECTs (sabendo que uns continuam a afectar os outros) e os resultados foram consistentes:

    SELECT campos INTO estrutura 24.955
    SELECT campos INTO CORRESPONDING estrutura 24.512
    SELECT campos INTO CORRESPONDING 144.042
    SELECT * 956.909

    Mas o mais cómico é que por engano corri o programa no mandante de desenvolvimentos, que não tem dados (a BSAD tem 0 registos) e o mais rápido foi de longe o SELECT * eh eh

Deixe um comentário


Acerca do Abapinho
O Abapinho é suportado pelo WordPress
Artigos (RSS) e Comentários (RSS).